Android JNI:Segfaults从C调用Java回调时
我有一个C语言库,我正在利用它来开发Android应用程序。这个库有一个偶尔刷新的音频流。当这种情况发生时,它调用我设计的写回调函数 我的意图是让C回调调用一个特定Java对象上的方法,该对象将处理strem的内容 目前我有这样的代码: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
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);
}