在Android中为JNI调用NewObjectArray时可能导致SIGSEGV的原因是什么?

时间:2010-01-21 22:05:07

标签: java-native-interface android-ndk

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

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

基于我能找到的所有示例,上面的代码是正确的,但我一直得到SIGSERGV,如果NewObjectArray行被注释掉,一切正常。知道什么可能导致这样的问题吗?

2 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:2)

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

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

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