You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 绿色

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:30:57