Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.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 JNI:Segfaults从C调用Java回调时_Android_C_Java Native Interface_Jnienv - Fatal编程技术网

Android JNI:Segfaults从C调用Java回调时

Android JNI:Segfaults从C调用Java回调时,android,c,java-native-interface,jnienv,Android,C,Java Native Interface,Jnienv,我有一个C语言库,我正在利用它来开发Android应用程序。这个库有一个偶尔刷新的音频流。当这种情况发生时,它调用我设计的写回调函数 我的意图是让C回调调用一个特定Java对象上的方法,该对象将处理strem的内容 目前我有这样的代码: methodID compressionHandler=0; jobject compressionHandlerClass; int audioBufferChunkSize; static JavaVM *gJavaVM; JNIEXPORT ji

我有一个C语言库,我正在利用它来开发Android应用程序。这个库有一个偶尔刷新的音频流。当这种情况发生时,它调用我设计的写回调函数

我的意图是让C回调调用一个特定Java对象上的方法,该对象将处理strem的内容

目前我有这样的代码:

methodID compressionHandler=0;
jobject compressionHandlerClass;
int audioBufferChunkSize;    
static JavaVM *gJavaVM;

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    gJavaVM = vm;
    return JNI_VERSION_1_6;
}

JNIEXPORT void JNICALL
Java_com_my_code_init(JNIEnv* env, jobject obj, /*classpath of the class we want to call against*/jstring compressedAudioHandlerPath, /*class instance we want to call against*/jobject callbackClass) {
......
// this is a global ref as per:
    //http://stackoverflow.com/questions/14765776/jni-error-app-bug-accessed-stale-local-reference-0xbc00021-index-8-in-a-tabl
    compressionHandlerClass = (*env)->NewGlobalRef(env,callbackClass);
    // name of the class
    const char *classLocation;
    // convert jString to c String
    classLocation = (*env)->GetStringUTFChars( env, compressedAudioHandlerPath , NULL ) ;
    // tmp variable for holding the class location, relates to the above issue with garbage collection
    jclass clazz = (*env)->FindClass(env, classLocation);

    // the actual method that we want to call, this gets used in the writeCallback
    compressionHandler = (*env)->GetMethodID(env, clazz, "handleCompressedAudio", "([B)V");
    ......
}
回调方法如下所示:

void writeCallback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data) {

JNIEnv *env;
int isAttached = 0;
if ((status = (*gJavaVM)->GetEnv(gJavaVM, (void**)&env, JNI_VERSION_1_6)) < 0) {
    if ((status = (*gJavaVM)->AttachCurrentThread(gJavaVM, &env, NULL)) < 0) {
            return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
    }
    isAttached = 1;
}
if(*env!=0 && compressionHandler!=0){
       jbyteArray arr = (*env)->NewByteArray(env,bytes);
       (*env)->SetByteArrayRegion(env,arr, 0, bytes, (jbyte*)buffer);
       (*env)->CallVoidMethod(env,compressionHandlerClass, compressionHandler,arr);
       free(arr);
       free(env);
       free(isAttached);
    }
}

我怀疑我获取/保留这些对象的引用不正确,但我还没有找到一个很好的方法来处理它。关于如何更正确地处理此问题,有什么建议吗?

关于传入obj的c端引用,您可能希望通过音频流接口651写入缓冲区上的类似内容读取,请参阅将来自java的对象转换为Cpp类型的转换部分。。。您不应该使用freearr,因为它是对Java字节数组的本地引用。改用DeleteLocalRef。另外,不应该释放env,而且显然也不应该进行isAttached,因为这只是一个int。如果isAttached为true,则应该调用DetachCurrentThread。谢谢。摆脱免费电话停止了故障。
public interface CompressedAudioHandler {
        void handleCompressedAudio(byte[] buff);
    }