在Android NDK中跨线程共享JavaVM *

时间:2012-04-20 05:32:49

标签: multithreading android-ndk java-native-interface

我想从接收来自另一个可执行文件的回调的cpp文件中调用Java类方法。

为了实现这一点,我使用直接接收JNI方法调用的.cpp文件中的 android :: AndroidRuntime :: getJavaVM()方法检索了一个JavaVM指针。我通过构造函数将此JavaVM指针共享到最终的.cpp文件,我在其中调用所需的Java方法,如下所示:

/* All the required objects(JNIEnv*,jclass,jmethodID,etc) are appropriately declared. */
**JNIEnv* env;
jvm->AttachCurrentThread(&env, NULL);
clazz = env->FindClass("com/skype/ref/NativeCodeCaller");
readFromAudioRecord = env->GetStaticMethodID(clazz, "readFromAudioRecord", "([B)I");
writeToAudioTrack = env->GetStaticMethodID(clazz, "writeToAudioTrack", "([B)I");** 

但是,运行此代码时出现 SIGSEGV 错误。

根据JNI文件,这似乎是在仲裁环境中获取JNIEnv的适当方式:http://java.sun.com/docs/books/jni/html/other.html#26206

在这方面的任何帮助将不胜感激。

此致 Neeraj

2 个答案:

答案 0 :(得分:2)

如果尝试使用JNIEnv或JavaVM引用而不将线程附加到VM,则全局引用不会阻止新线程中的分段错误。你第一次正确地做到了这一点,MārtiņšMožeiko错误地暗示你所做的事情有问题。

不要删除它,只是学习如何使用它。那家伙不知道他在说什么,如果是在jni.h你可以肯定它不会去任何地方。它没有被记录的原因可能是因为它是可笑的自我解释。您不需要创建GlobalReference对象或其他任何东西,只需执行以下操作:

#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>
#include <linux/threads.h>
#include <pthread.h>

#define  LOG_TAG    "[NDK]"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

static pthread_mutex_t thread_mutex;
static pthread_t thread;
static JNIEnv* jniENV;

void *threadLoop()
{
    int exiting;
    JavaVM* jvm;
    int gotVM = (*jniENV)->GetJavaVM(jniENV,&jvm);
    LOGI("Got JVM: %s", (gotVM ? "false" : "true") );
    jclass javaClass;
    jmethodID javaMethodId;
    int attached = (*jvm)->AttachCurrentThread(jvm, &jniENV,NULL);
    if(attached>0)
    {
        LOGE("Failed to attach thread to JavaVM");
        exiting = 1;
    }
    else{
        javaClass= (*jniENV)->FindClass(jniENV, "com/justinbuser/nativecore/NativeThread");
        javaMethodId= (*jniENV)->GetStaticMethodID(jniENV, javaClass, "javaMethodName", "()V");
    }
    while(!exiting)
    {
        pthread_mutex_lock(&thread_mutex);
        (*jniENV)->CallStaticVoidMethod(jniENV, javaClass, javaMethodId);
        pthread_mutex_unlock(&thread_mutex);
    }
    LOGE("Thread Loop Exiting");
    void* retval;
    pthread_exit(retval);
    return retval;
}

void start_thread(){
    if(thread < 1)
        {
            if(pthread_mutex_init(&thread_mutex, NULL) != 0)
            {
                LOGE( "Error initing mutex" );
            }
            if(pthread_create(&thread, NULL, threadLoop, NULL) == 0)
            {
                LOGI( "Started thread#: %d", thread);
                if(pthread_detach(thread)!=0)
                {
                    LOGE( "Error detaching thread" );
                }
            }
            else
            {
                LOGE( "Error starting thread" );
            }
        }
}

JNIEXPORT void JNICALL
Java_com_justinbuser_nativecore_NativeMethods_startThread(JNIEnv * env, jobject this){
    jniENV = env;
    start_thread();
}

答案 1 :(得分:0)

解决了这个问题。分段错误是因为我无法从共享jvm指针检索到的JNIEnv对象中检索jclass对象。

我与jvm一起传播了一个全局引用jclass对象,问题解决了。

感谢您的帮助MārtiņšMožeiko!..

此致 Neeraj