【问题标题】:What could cause SIGSEGV when calling NewObjectArray for JNI in Android?在 Android 中为 JNI 调用 NewObjectArray 时可能导致 SIGSEGV 的原因是什么?
【发布时间】:2010-01-21 22:05:06
【问题描述】:

我刚开始使用 Android NDK,但是当我在 C 代码中调用此调用时,我不断收到 SIGSEGV:

jobjectArray someStringArray;
someStringArray = (*env)->NewObjectArray(env, 10, 
(*env)->FindClass(env,"java/lang/String"),(*env)->NewStringUTF(env, ""));

根据我能找到的所有示例,上面的代码是正确的,但我不断收到 SIGSERGV,如果 NewObjectArray 行被注释掉,一切正常。知道什么会导致这样的问题吗?

【问题讨论】:

  • 忘了说,我用的是NDK1.6

标签: java-native-interface android-ndk


【解决方案1】:

看起来不错,所以我猜你做错了什么。我假设您正在使用 checkjni 运行?您可能希望将其分成多行:执行 FindClass 并检查返回值,执行 NewStringUTF 并检查返回值,然后调用 NewObjectArray。

顺便说一句,您可能希望将 NULL 作为最后一个参数传递;这种使用空字符串作为数组每个元素的默认值的模式很常用(我认为它是从一些 Sun 文档中复制和粘贴的,并且已经从那里传播开来),但它很少有用,而且有点浪费。 (并且它与 Java 中“new String[10]”的行为不匹配。)

【讨论】:

    【解决方案2】:

    我猜可能的原因之一是在长期运行的 JNI 方法中,当每个方法调用的本地引用槽(Android 中通常为 512 个槽)用完时,VM 会中止。

    由于 FindClass() 和 NewStringUTF() 函数会分配本地引用,如果你长时间停留在 JNI 方法中,VM 不知道是否应该回收特定的本地引用。因此,您应该在不再需要时显式调用 DeleteLocalRef() 以释放获取的本地引用。如果不这样做,“僵尸”本地引用将占用 VM 中的插槽,并且 VM 在用完所有本地引用插槽时中止。

    在短期 JNI 方法中,这可能不是问题,因为退出 JNI 方法时所有本地引用都会被回收。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-25
      • 2013-04-01
      相关资源
      最近更新 更多