У меня есть некоторый JNI-код в потоке, который вызывает из Java в C. Код работает, но если я окажу на него слишком большое давление (выполним слишком много инструкций), он вылетит:
W/dalvikvm( 1502): JNI local reference table summary (512 entries):
W/dalvikvm( 1502): 512 of Ljava/lang/Class; 164B (1 unique)
W/dalvikvm( 1502): Memory held directly by tracked refs is 164 bytes
E/dalvikvm( 1502): Failed adding to JNI local ref table (has 512 entries)
I/dalvikvm( 1502): "Thread-17" prio=5 tid=10 RUNNABLE
I/dalvikvm( 1502): | group="main" sCount=0 dsCount=0 s=N obj=0x40114910 self=0xd3d40
I/dalvikvm( 1502): | sysTid=1542 nice=0 sched=0/0 cgrp=default handle=821104
I/dalvikvm( 1502): | schedstat=( 359863282 630188006 2660 )
I/dalvikvm( 1502): at dalvik.system.NativeStart.run(Native Method)
I/dalvikvm( 1502):
E/dalvikvm( 1502): VM aborting
I/DEBUG ( 1011): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 1011): Build fingerprint: 'verizon/voles/sholes/sholes:2.2.2/FRG83G/91102:user/release-keys'
I/DEBUG ( 1011): pid: 1502, tid: 1542 >>> app_process <<<
I/DEBUG ( 1011): signal 11 (SIGSEGV), fault addr deadd00d
I/DEBUG ( 1011): r0 00000026 r1 afd14629 r2 afd14629 r3 00000000
I/DEBUG ( 1011): r4 805a23f4 r5 805a23f4 r6 000d3d40 r7 000d3d90
I/DEBUG ( 1011): r8 00100000 r9 80601f45 10 449f1000 fp 4453ed90
I/DEBUG ( 1011): ip deadd00d sp 44af0dc0 lr afd15673 pc 805420b8 cpsr 20000030
При вызове из Java в C я сохраняю GlobalReference для класса, который хочу вызвать, а затем создаю новый поток:
JNIEXPORT void JNICALL Java_com_device_client_HostConnection_initialize
(JNIEnv * env, jobject obj, jobject inject)
{
JavaVM *tmpVM;
jint result = env->GetJavaVM(&tmpVM);
if (result < 0) {
LOGE("Error using GetJavaVM\n");
exit(-1);
}
jobject tmpHostObject = env->NewGlobalRef(inject);
if (tmpHostObject == NULL) {
LOGE("ERROR: Run out of memory for weak global ref\n");
exit(-1);
}
vm = tmpVM;
hostObject = tmpHostObject;
pthread_t pth;
pthread_create(&pth, NULL, startServer, NULL);
pthread_join(pth, NULL);
}
Здесь vm и hostObject являются глобальными переменными. В моем новом потоке я вызываю метод Java из объекта ввода, который я передал, и создал GobalRef для:
void *startServer(void* arg)
{
JNIEnv* env = NULL;
jmethodID mid;
jclass hostClass;
vm->AttachCurrentThread(&env, NULL);
while (run) {
/* some code */
/* Calls a new thread */
pthread_t pth;
pthread_create(&pth, NULL, receive, NULL);
/* more code */
}
vm->DetachCurrentThread();
}
void *receive()
{
jmethodID mid;
jclass hostClass;
JNIEnv* env = NULL;
vm->AttachCurrentThread(&env, NULL)
while (1) {
/* receive x, y and action */
hostClass = env->GetObjectClass(hostObject);
mid = env->GetMethodID(hostClass, "executeTouch", "(III)V");
if (mid == 0) {
LOGD("ERROR: GetMethodID\n");
exit(-1);
}
env->CallVoidMethod(hostObject, mid, x * 2, y * 2, action);
}
vm->DetachCurrentThread();
}
Кто-нибудь знает, пожалуйста, что происходит? У меня заканчивается память, пожалуйста? Почему это так и как я могу избежать этого?
EDIT:
Я понял, что мне не нужно постоянно получать MethodID, я мог просто сохранить его локально до того, как время (1). Это исправило мою проблему! Извините за вопрос, спасибо.
Большое спасибо.