JNI中填充ArrayList触发段错误,求问题原因排查
JNI调用List.add触发段错误的原因及修复方案
问题出在参数类型不匹配:Java的List.add(Object)方法要求传入对象类型,但你直接传了jint基本类型,JNI不会自动完成基本类型到包装类的装箱操作,导致方法调用时内存访问出错。
具体分析
Java中List<Integer>.add()实际接收的是Integer对象,而你在C++代码里直接传递(jint)i——这是一个32位整数,不是JNI的对象引用。JNI调用方法时会把这个整数当作对象指针去访问,自然会触发段错误。
修复后的C++代码
需要手动把jint装箱成Integer对象,再传给add方法:
JNIEXPORT void JNICALL Java_Main_fill (JNIEnv *env, jclass cls, jobject jList, jint jn) { // 获取List类 jclass jListCls = env->GetObjectClass(jList); // 获取List.add(Object)方法ID jmethodID jListAddMethod = env->GetMethodID(jListCls, "add", "(Ljava/lang/Object;)Z"); // 获取Integer类及其(int)构造方法 jclass integerCls = env->FindClass("java/lang/Integer"); jmethodID integerCtor = env->GetMethodID(integerCls, "<init>", "(I)V"); for (int i = 0; i < jn; i++) { // 将jint包装成Integer对象 jobject integerObj = env->NewObject(integerCls, integerCtor, (jint)i); // 调用add方法 env->CallBooleanMethod(jList, jListAddMethod, integerObj); // 释放临时创建的Integer对象引用 env->DeleteLocalRef(integerObj); } // 释放局部引用 env->DeleteLocalRef(jListCls); env->DeleteLocalRef(integerCls); }
注意事项
- JNI没有自动装箱/拆箱机制,必须手动处理基本类型和包装类的转换
- 临时创建的JNI对象引用(比如
integerObj)用完后要及时释放,避免局部引用表溢出 - 确认方法签名正确:
add方法的签名是(Ljava/lang/Object;)Z,返回布尔值,这个你之前是对的
内容的提问来源于stack exchange,提问作者Green 绿色
相关产品推荐
相关产品推荐

