1

出于某种原因,当我尝试从一个线程访问一个 java 对象(它在整个程序中持续存在,顺便说一句)时,程序崩溃了。这是一个简化的示例来演示该问题:

#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;
}

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

4

2 回答 2

2

好的,问题似乎是缺少 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;
}
于 2013-09-19T15:13:16.093 回答
0

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

由于从“AttachCurrentThread”到“DetachCurrentThread”的整个过程没有被锁定,所以在某些情况下,在“run”完成之前,主线程可能会重新“AttachCurrentThread”。这样还是会有问题的。

于 2014-11-19T15:11:09.883 回答