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

时间:2015-01-02 15:10:55

标签: android c java-native-interface jnienv

我是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);
    }
}

我在CallVoidMethod上遇到崩溃,其签名是我传入的任何对象实现的接口:

public interface CompressedAudioHandler {
        void handleCompressedAudio(byte[] buff);
    }

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

0 个答案:

没有答案