JNI:从线程崩溃中调用CallVoidMethod

时间:2013-09-19 08:09:45

标签: multithreading java-native-interface

出于某种原因,当我尝试从一个线程访问一个java对象(在整个程序中持续存在BTW)时,程序崩溃了。这里有一个简单的例子来证明这个问题:

#include <jni.h>
#include <pthread.h>
pthread_t thread;
jobject object;
JavaVM* jvm;
/*
    Our thread function:
*/
void* run( void* );
extern "C" void Java_com_Program_Initialize( JNIEnv* jnv, jobject caller )
{
    object = caller;
    jnv->GetJavaVM( &jvm );
/*
    Before launching our thread, this works just fine:
*/  
    jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) );
    pthread_create( &thread, NULL, run, NULL );
}
void* run( void* )
{
    JNIEnv* jnv;
    jvm->AttachCurrentThread( &jnv, NULL );
/*
    Within the context of our thread however, this crashes:
*/  
    jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) );     
    jvm->DetachCurrentThread( );
    return NULL;
}

关于出了什么问题的任何想法?

2 个答案:

答案 0 :(得分:1)

好的,问题似乎是缺少NewGlobalRef调用。这个版本有效:

#include <jni.h>
#include <pthread.h>
pthread_t thread;
jobject object;
JavaVM* jvm;
/*
    Our thread function:
*/
void* run( void* );
extern "C" void Java_com_Program_Initialize( JNIEnv* jnv, jobject caller )
{
    object = jnv->NewGlobalRef( caller );
    jnv->GetJavaVM( &jvm );
    pthread_create( &thread, NULL, run, NULL );
}
void* run( void* )
{
    JNIEnv* jnv;
    jvm->AttachCurrentThread( &jnv, NULL );
    jnv->CallVoidMethod( object, jnv->GetMethodID( jnv->GetObjectClass( object ), "foo", "()V" ) ); 
    jnv->DeleteGlobalRef( object );     
    jvm->DetachCurrentThread( );
    return NULL;
}

答案 1 :(得分:0)

我建议您尝试找一种方法将调用发布到主线程。

由于整个过程来自&#34; AttachCurrentThread&#34; to&#34; DetachCurrentThread&#34;没有锁定,主线程可能会重新&#34; AttachCurrentThread&#34;,在某些情况下,在&#34;运行&#34;完了。因此仍然存在问题。