Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法在任意上下文中获取JNIEnv*值_Android_C_Java Native Interface_Android Ndk - Fatal编程技术网

Android 无法在任意上下文中获取JNIEnv*值

Android 无法在任意上下文中获取JNIEnv*值,android,c,java-native-interface,android-ndk,Android,C,Java Native Interface,Android Ndk,我对NDK有意见 在我的JNI_OnLoad方法中,我缓存了JavaVm指针、调用该方法的类以及稍后使用的方法id: JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; cachedJVM = jvm; if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6)){ LOG_ERROR("Cou

我对NDK有意见

在我的JNI_OnLoad方法中,我缓存了JavaVm指针、调用该方法的类以及稍后使用的方法id:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved){
    JNIEnv *env;
    cachedJVM = jvm;
    if((*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6)){
        LOG_ERROR("Could not get JNIEnv*");
        return JNI_ERR;
    }
    javaClass = (*env)->FindClass(env, "org/test/opensl/AudioProcessor");
    if(javaClass == NULL){
        LOG_ERROR("Could not get java class");
        return JNI_ERR;
    }
    javaCallbackMID = (*env)->GetMethodID(env, javaClass, "enqueueAudio", "([B)V");
    if(javaCallbackMID == NULL){
        LOG_ERROR("Could not get method identifier");
        return JNI_ERR;
    }
    return JNI_VERSION_1_6;
}
我有一个定义如下的小实用程序方法,它应该会给我一个指向JNIEnv的指针:

JNIEnv* JNU_GetEnv(){
    JNIEnv* env;
    (*cachedJVM)->GetEnv(cachedJVM, (void**)&env, JNI_VERSION_1_6);
    return env;
}
最后,我有一个来自OpenSL ES
SLAndroidSimpleBufferQueueItf
的回调,我想处理来自
SLRecordItf
的录制音频:

void recorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
    SLresult result;
    JNIEnv* env;
    recorderContext* thisContext = (recorderContext*)context;
    env = JNU_GetEnv();
    if(env == NULL){
        LOG_ERROR("Could not get JNIEnv*");
        return;
    }
    jbyteArray data = (*env)->NewByteArray(env, MAX_PACKET_SIZE);
    if(data == NULL){
        LOG_ERROR("No memory could be allocated for buffer");
        return;
    }
    (*env)->SetByteArrayRegion(env, data, 0, MAX_PACKET_SIZE, recorderBuffer);
    (*env)->CallByteMethodA(env, thisContext->caller, javaCallbackMID, data);
    (*env)->DeleteLocalRef(env, data);
    result = (*bq)->Enqueue(bq, recorderBuffer,
                            RECORDER_FRAMES * sizeof(jbyte));
    checkError(result, "Unable to enqueue new buffer");
}
其中回调方法的上下文参数仅包含对调用本机方法的对象的引用。它是一个自定义结构,如下所示:

typedef struct recorderContext{
    jobject caller;
} recorderContext;
然而,每次我尝试运行这个函数时,我都会从回调方法中得到
“cannotgetjnienv*”
错误消息

我的问题基本上可以归结为:为什么我可以在JNI_OnLoad方法中获得一个指向JNIEnv的指针,而不是在recorderCallback中,因为两者都使用相同的Java VM指针来获得JNIEnv

我需要这个回调来将录制的音频传递回Java层进行进一步处理

为什么我可以得到一个指向JNIEnv的指针 在JNI_OnLoad方法中,但不是在 记录器回调,因为两者都使用 相同的JavaVM指针来获取 JNIEnv

因为回调发生在一些本机线程上,与加载库的VM线程不同。JNI实现为每个线程维护一个
JNIEnv
,并将指针放在线程本地存储中。它仅针对连接到VM的本机线程进行初始化。您需要在回调中调用
AttachCurrentThread()
(或者更可能是
AttachCurrentThreadAsDaemon()
),以获取对该线程有效的
JNIEnv
指针。这会在第一次调用时将线程附加到VM,并且在之后是nop


警告:这个答案假设Java是正确的。您看到的问题表明Dalvik的行为与JVM相同。

您的回答也帮助了我。我在一个VM线程中初始化了JNIEnv ptr,并认为ptr可以在另一个VM线程中使用。但在多次使用ptr后,我收到了SIGSEGV。这也帮助了我。但是我遇到了一个问题,JNI_Onload()没有被调用(甚至找不到),尽管符号在我的.so中。因为我来自C++,所以我在JavaIn中添加了JNION Load()。