java - JNI GetShortArrayElements 因 SIGSEGV SEGV_ACCERR 而失败

标签 java android c++ java-native-interface kotlin

我在托管代码中创建了一个缓冲区:

var nativeBuffer = ShortArray(bufferSize)

这是 Kotlin 代码,但根据 stdlib documentation ,此语法实际上是一个返回 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 是一个“输出参数”(使用 C# 术语)。

如果您不关心 targetArray 是否是 javaArray 的别名,您也可以传递 nullptr,如下所示:

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

关于java - JNI GetShortArrayElements 因 SIGSEGV SEGV_ACCERR 而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33590158/

相关文章:

android - 关闭和重新打开 Android 应用程序

c++ - 为什么在比较范围内的数字时,汇编代码中会出现分支?

java - 在单词中的每个字符之间插入一个字符(a 到 z)

java - 在 Java 多线程环境中分配唯一代理

java - java中的数字除以零值

android - bash 传递参数无效(adb)

java - 如何用不同类型的方法覆盖方法?

android - 删除项目后如何更新列表?

c++ - 在运行我在 cpp 中编译的程序时将文件名作为输入

c++ - openMP 没有并行线程