Android JNI: GetObjectClass se bloquea con SIGSEGV (no es una referencia JNI válida)

Estoy intentando crear un nuevo hilo, así que estoy pasando la VM de mi método initialize (llamado de Java) a mi nuevo hilo. En el hilo, llamo AttachCurrentThread y obtengo el JNIEnv * env.

Más adelante, intento llamar a GetObjectClass con el entorno y se bloquea. Creo que esto es porque el objeto no puede ser inicializar, pero estoy tratando de llamar a un método que se define en la clase que contiene el método nativo. He estado tratando de seguir la Sección 4.2 (principio) de http://java.sun.com/docs/books/jni/html/fldmeth.html .

Algo muy extraño: estoy probando con un HTC Dream corriendo 2.2 y el siguiente código no se bloquea, pero con un Motorola Droid ejecutando 2.2.2 se bloquea todo el tiempo!

Este es mi código:

C ++

JNIEXPORT void JNICALL Java_com_device_client_HostConnection_initialize (JNIEnv * env, jobject obj, jint port) { JavaVM *vm; jint result = env->GetJavaVM(&vm); if (result < 0) { LOGE("Error using GetJavaVM\n"); exit(-1); } struct javaInfo* data = (struct javaInfo*) malloc(sizeof(struct javaInfo)); data->vm = vm; data->javaObjHost = obj; pthread_t pth; pthread_create(&pth, NULL, startServer, (void *) data); } 

El nuevo hilo:

 void *startServer(void* arg) { jclass cls; jmethodID mid; JNIEnv* env = NULL; struct javaInfo* data = (struct javaInfo*) arg; JavaVM* vm = data->vm; jobject javaObjHost = data->javaObjHost; if (vm == NULL) { LOGE("VM is null\n"); } vm->AttachCurrentThread(&env, NULL); cls = env->GetObjectClass(javaObjHost); mid = env->GetMethodID(cls, "setStatus", "(Z)V"); if (mid == 0) { LOGD("ERROR: GetMethodID\n"); exit(-1); } env->CallVoidMethod(javaObjHost, mid, false); 

La línea cls = env-> GetObjectClass (javaObjHost); Se bloquea con la siguiente salida:

 W/dalvikvm( 5827): JNI WARNING: 0x44872da0 is not a valid JNI reference W/dalvikvm( 5827): in Ldalvik/system/NativeStart;.run ()V (GetObjectClass) I/dalvikvm( 5827): "Thread-9" prio=5 tid=8 RUNNABLE I/dalvikvm( 5827): | group="main" sCount=0 dsCount=0 s=N obj=0x448734c8 self=0x229da8 I/dalvikvm( 5827): | sysTid=5834 nice=0 sched=0/0 cgrp=default handle=2265136 I/dalvikvm( 5827): | schedstat=( 885010 3631591 2 ) I/dalvikvm( 5827): at dalvik.system.NativeStart.run(Native Method) I/dalvikvm( 5827): E/dalvikvm( 5827): VM aborting I/DEBUG ( 5511): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** I/DEBUG ( 5511): Build fingerprint: 'verizon/voles/sholes/sholes:2.2.2/FRG83G/91102:user/release-keys' I/DEBUG ( 5511): pid: 5827, tid: 5834 >>> com.device.client <<< I/DEBUG ( 5511): signal 11 (SIGSEGV), fault addr deadd00d .... 

Mi código java:

 public class HostConnection { static { System.loadLibrary("hostConnection"); } public void setStatus(boolean bool) { ... } public native void initialize(int defaultPort); } 

¿Podría alguien ayudarme por favor? Me gustaría llamar al método setStatus () dentro de mi clase, sin crear un nuevo objeto.

EDITAR:

Este es el nuevo código, se está estrellando en el momento de estrellarse.

 JNIEXPORT void JNICALL Java_com_device_client_HostConnection_initialize (JNIEnv * env, jobject obj, jint port) { JavaVM *vm; jint result = env->GetJavaVM(&vm); if (result < 0) { LOGE("Error using GetJavaVM\n"); exit(-1); } jclass clsLocal = env->GetObjectClass(obj); if (clsLocal == NULL) { LOGE("ERROR: Cannot find class HostConnection\n"); exit(-1); } jclass hostClass = (jclass) env->NewWeakGlobalRef(clsLocal); if (hostClass == NULL) { LOGE("ERROR: Run out of memory for weak global ref\n"); exit(-1); } struct javaInfo* data = (struct javaInfo*) malloc(sizeof(struct javaInfo)); data->vm = vm; data->hostClass = hostClass; pthread_t pth; pthread_create(&pth, NULL, startServer, (void *) data); } void *startServer(void* arg) { JNIEnv* env = NULL; jmethodID mid; struct fb_var_screeninfo vinfo; char server[MAXHOSTNAMELEN]; struct javaInfo* data = (struct javaInfo*) arg; JavaVM* vm = data->vm; jclass hostClass = data->hostClass; if (vm == NULL) { LOGE("VM is null\n"); } vm->AttachCurrentThread(&env, NULL); mid = env->GetMethodID(hostClass, "setStatus", "(Z)V"); if (mid == 0) { LOGD("ERROR: GetMethodID\n"); exit(-1); } env->CallVoidMethod(hostClass, mid, false); } 

Estoy recibiendo el siguiente accidente:

 W/dalvikvm( 7650): JNI WARNING: jclass points to invalid object 0xda88d23f I/dalvikvm( 7650): "Thread-9" prio=5 tid=8 NATIVE I/dalvikvm( 7650): | group="main" sCount=0 dsCount=0 s=N obj=0x448734f8 self=0x228a20 I/dalvikvm( 7650): | sysTid=7657 nice=0 sched=0/0 cgrp=default handle=2260192 I/dalvikvm( 7650): | schedstat=( 854493 9155273 2 ) I/dalvikvm( 7650): at dalvik.system.NativeStart.run(Native Method) I/dalvikvm( 7650): E/dalvikvm( 7650): VM aborting I/DEBUG ( 5511): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** I/DEBUG ( 5511): Build fingerprint: 'verizon/voles/sholes/sholes:2.2.2/FRG83G/91102:user/release-keys' I/DEBUG ( 5511): pid: 7650, tid: 7657 >>> com.device.client <<< I/DEBUG ( 5511): signal 11 (SIGSEGV), fault addr deadd00d 

Sé que se bloquea en GetMethodID (). Realmente no estoy seguro de por qué. Cualquier ayuda sería muy apreciada.

Muchas gracias.

Estás recibiendo el object de Java_com_device_client_HostConnection_initialize como una referencia local, y luego lo pasas a tu nuevo hilo en tu estructura javaInfo .

La referencia local es válida sólo en el subproceso actual, de la misma manera que el puntero JNIEnv* .

Por lo tanto, cuando se obtiene de la estructura en el nuevo hilo, tiene una referencia no válida al objeto, lo que explica el bloqueo.

Trate de obtener una referencia WeakGlobal en el método NewWeakGlobalRef utilizando el método JNIEnv de JNIEnv .

Lea el capítulo cinco de los documentos de la JNI para entender las diferencias entre las referencias globales locales, globales y débiles.

  • Cómo vincular cualquier biblioteca en la aplicación ndk
  • Depuración del código Android NDK C / C ++ en Eclipse: los puntos de interrupción no se alcanzan
  • Devuelve jbyteArray desde c nativo en Android
  • Libusb_open_device_with_vid_pid falló al intentar acceder al dispositivo USB
  • Android JNI: root-making deadd00d (dvmAbort)
  • El proceso de alojamiento del servicio de cámara ha muerto inesperadamente
  • Java.lang.UnsatisfiedLinkError: Método nativo no encontrado: Error en jni ()
  • JNIEXPORT y JNICALL en Android NDK
  • Llamar al miembro de la clase JAVA desde el código nativo C / C ++
  • Extraer código de archivo .aar Android
  • Android: Uso de JNI desde NativeActivity
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.