通过其他线程通过JNI呼叫保存的Java对象

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

本文关键字:对象 保存 Java JNI 其他 线程 呼叫      更新时间:2023-10-16

我有一个Java对象,该对象通过JNI调用C 共享对象。在C 中,我保存了对Jnienv和Jobject的引用。

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

我也有一个glsurface渲染器,它最终称为上面在其他线程(glthread)上提到的C 共享对象。然后,我试图使用最初保存的Jobight回到我的原始Java对象中,但是我认为因为我在glthread上,我会收到以下错误。

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

返回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); 

}

相反,如果我使用env-> newObject创建了一个新的职位,我可以将其助理回Java,但这是一个新对象,我不想要它。我需要回到我的原始Java对象。

在我回到Java之前切换线程是一个问题吗?如果是这样,我该怎么办?

从不同线程访问对象是可以的。问题是JNI调用将对象作为本地引用。如果您想在JNI调用之间参考JNI调用之间的验证,则需要将其全局参考:

myobj = env->NewGlobalRef(jObj);

完成使用后要释放它,否则垃圾收集器不会收集它,您将获得内存泄漏:

myEnv->DeleteGlobalRef(myobj);

在此处阅读有关全局与本地参考的信息。