JNI GetShortArrayElements 失败并显示 SIGSEGV SEGV_ACCERR
JNI GetShortArrayElements fails with SIGSEGV SEGV_ACCERR
我在托管代码中创建了一个缓冲区:
var nativeBuffer = ShortArray(bufferSize)
这是 Kotlin 代码,但根据 stdlib documentation,此语法实际上是 returns 和 short []
.
的包装器
然后我想使用 JNI 从 C++ 写入此缓冲区:
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+ 进行了测试。我还能错过什么?
糟糕,您没有正确使用 isCopy
参数。应该是:
jboolean isCopy;
jshort* targetArray = env->GetShortArrayElements(javaArray, &isCopy);
也就是说,isCopy
是一个 "out parameter"(使用 C# 术语)。
如果您不关心 targetArray
是否是 javaArray
的别名,您也可以传递 nullptr
代替,如下所示:
jshort* targetArray = env->GetShortArrayElements(javaArray, nullptr);
目标数组应该是 jshort 而不是 short.
您还需要使用 & 而不是按值传递 isCopy 通过引用。
更多信息在这里:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp17382
我在托管代码中创建了一个缓冲区:
var nativeBuffer = ShortArray(bufferSize)
这是 Kotlin 代码,但根据 stdlib documentation,此语法实际上是 returns 和 short []
.
然后我想使用 JNI 从 C++ 写入此缓冲区:
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+ 进行了测试。我还能错过什么?
糟糕,您没有正确使用 isCopy
参数。应该是:
jboolean isCopy;
jshort* targetArray = env->GetShortArrayElements(javaArray, &isCopy);
也就是说,isCopy
是一个 "out parameter"(使用 C# 术语)。
如果您不关心 targetArray
是否是 javaArray
的别名,您也可以传递 nullptr
代替,如下所示:
jshort* targetArray = env->GetShortArrayElements(javaArray, nullptr);
目标数组应该是 jshort 而不是 short.
您还需要使用 & 而不是按值传递 isCopy 通过引用。
更多信息在这里: http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp17382