Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling into a saved java object via JNI from a different thread

Tags:

I have a java object which calls into a C++ shared object via JNI. In C++, I am saving a reference to the JNIEnv and jObject.

JavaVM * jvm; JNIEnv * myEnv; jobject myobj;  JNIEXPORT void JNICALL Java_org_api_init    (JNIEnv *env, jobject jObj) {     myEnv = env;     myobj = jObj; } 

I also have a GLSurface renderer and it eventually calls the C++ shared object mentioned above on a different thread, the GLThread. I am then trying to call back into my original Java object using the jobject I saved initially, but I think because I am on the GLThread, I get the following error.

W/dalvikvm(16101): JNI WARNING: 0x41ded218 is not a valid JNI reference I/dalvikvm(16101): "GLThread 981" prio=5 tid=15 RUNNABLE I/dalvikvm(16101):   | group="main" sCount=0 dsCount=0 obj=0x41d6e220 self=0x5cb11078 I/dalvikvm(16101):   | sysTid=16133 nice=0 sched=0/0 cgrp=apps handle=1555429136 I/dalvikvm(16101):   | schedstat=( 0 0 0 ) utm=42 stm=32 core=1 

The code calling back into Java :

void setData()     {         jvm->AttachCurrentThread(&myEnv, 0);          jclass javaClass = myEnv->FindClass("com/myapp/myClass");         if(javaClass == NULL){             LOGD("ERROR - cant find class");         }          jmethodID method = myEnv->GetMethodID(javaClass, "updateDataModel", "()V");         if(method == NULL){             LOGD("ERROR - cant access method");         }          // this works, but its a new java object         //jobject myobj2 = myEnv->NewObject(javaClass, method);          //this is where the crash occurs         myEnv->CallVoidMethod(myobj, method, NULL);  

}

If instead I create a new jObject using env->NewObject, I can succuessfully call back into Java, but it is a new object and I dont want that. I need to get back to my original Java Object.

Is it a matter of switching threads before I call back into Java? If so, how do I do so ?

like image 221
Drake Amara Avatar asked Dec 20 '12 02:12

Drake Amara


People also ask

Does JNI makes the Java code machine dependent?

It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications and libraries written in other programming languages, such as C, C++, and assembly. The most important benefit of the JNI is that it imposes no restrictions on the implementation of the underlying Java VM.

What is JNI Jobject?

jobject thiz means the this in java class. Sometimes if you create a static native method like this. void Java_MyClass_method1 (JNIEnv *, jclass); jclass means the class itself. Follow this answer to receive notifications.

What is ENV JNI?

env : the JNI interface pointer. name : the name of the class or interface to be defined.

What is JNI reference?

JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).


1 Answers

Accessing object from different threads is fine. Problem is that JNI calls get objects as local references. If you want to keep reference to jobject between JNI calls you need to make it global reference:

myobj = env->NewGlobalRef(jObj); 

Remember to free it after you're done using it otherwise garbage collector won't collect it and you'll get memory leaks:

myEnv->DeleteGlobalRef(myobj); 

Read about global vs local references here.

like image 57
Mārtiņš Možeiko Avatar answered Oct 17 '22 08:10

Mārtiņš Možeiko