2015-11-08 59 views
1

我创建了一个托管代码的缓冲区:JNI GetShortArrayElements失败SIGSEGV SEGV_ACCERR

var nativeBuffer = ShortArray(bufferSize) 

这是科特林代码,但根据stdlib documentation,这句法实际上是一个返回short []的包装。

我会那么喜欢写从C++这个缓冲区,使用JNI:

JNIEXPORT void JNICALL Java_package_class_name_readNext 
    (JNIEnv * env, jclass clazz, jshortArray javaArray) 
{ 
    jboolean * isCopy; 
    short * targetArray = env->GetShortArrayElements(javaArray, isCopy); 

    // Do stuff to targetArray 
} 

的问题是,GetShortArrayElements电话始终会导致死机,用下面的墓碑:

11-07 21:23:53.610 86-86/? I/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 
11-07 21:23:53.610 86-86/? I/DEBUG: Build fingerprint: 'generic/vbox86p/vbox86p:5.1/LMY47D/buildbot06092001:userdebug/test-keys' 
11-07 21:23:53.610 86-86/? I/DEBUG: Revision: '0' 
11-07 21:23:53.610 86-86/? I/DEBUG: ABI: 'x86' 
11-07 21:23:53.610 86-86/? I/DEBUG: pid: 28339, tid: 28477, name: Thread-282 >>> <package-name> <<< 
11-07 21:23:53.610 86-86/? I/DEBUG: signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xb3bcfacb 
11-07 21:23:53.613 86-86/? I/DEBUG:  eax b3bcfacb ebx b3ffcaa4 ecx a2497000 edx b426e480 
11-07 21:23:53.613 86-86/? I/DEBUG:  esi a2497000 edi b3fff440 
11-07 21:23:53.613 86-86/? I/DEBUG:  xcs 00000073 xds 0000007b xes 0000007b xfs 000000e7 xss 0000007b 
11-07 21:23:53.613 86-86/? I/DEBUG:  eip b3dcd69c ebp 9f5a2968 esp 9f5a2880 flags 00210282 
11-07 21:23:53.613 86-86/? I/DEBUG:  #00 pc 002e069c /system/lib/libart.so (short* art::JNI::GetPrimitiveArray<_jshortArray*, short, art::mirror::PrimitiveArray<short> >(_JNIEnv*, _jshortArray*, unsigned char*)+572) 
11-07 21:23:53.613 86-86/? I/DEBUG:  #01 pc 0010cdad /system/lib/libart.so (art::CheckJNI::GetShortArrayElements(_JNIEnv*, _jshortArray*, unsigned char*)+125) 

javaArray不为空(通常是类似-1621480864的地址),nativeBuffer是一个静态变量,因此不可能被GC化。该行为发生在Genymotion实例(x86)和ARM设备上,但我只针对Android 5.0+进行了测试。我还能错过什么?

回答

3

糟糕,您没有正确使用isCopy参数。它应该是:

jboolean isCopy; 
jshort* targetArray = env->GetShortArrayElements(javaArray, &isCopy); 

也就是说,isCopy是一个 “输出参数”(使用C#行话)。

如果你不关心targetArray是否化名为javaArray,你也可以通过nullptr代替,就像这样:

jshort* targetArray = env->GetShortArrayElements(javaArray, nullptr);