JNI中如何从C++侧返回ArrayList<Boolean>?
解决JNI中创建并返回ArrayList的SIGSEGV错误
问题根源
触发SIGSEGV的核心原因有两个:
- ArrayList的
add(Object)方法要求传入引用类型,但直接传递jboolean基本类型时,JVM无法将其当作Object处理,导致内存访问错误。 - 调用
ArrayList无参构造函数时,错误地多传入了空字符串参数,与<init>()V的方法签名不匹配。
修正后的C++代码
需要将jboolean装箱为Java的Boolean对象后,再传入add方法。以下是完整修正实现:
JNIEXPORT jobject JNICALL Java_createArrayJNI_creatArray (JNIEnv *env, jobject thisObject) { // 1. 获取ArrayList类与无参构造方法 jclass array_list_cls = env->FindClass("java/util/ArrayList"); if (array_list_cls == NULL) return NULL; jmethodID array_list_ctor = env->GetMethodID(array_list_cls, "<init>", "()V"); if (array_list_ctor == NULL) return NULL; jobject array_list_obj = env->NewObject(array_list_cls, array_list_ctor); if (array_list_obj == NULL) return NULL; // 2. 获取Boolean类与valueOf静态装箱方法 jclass boolean_cls = env->FindClass("java/lang/Boolean"); if (boolean_cls == NULL) return NULL; jmethodID boolean_valueOf = env->GetStaticMethodID(boolean_cls, "valueOf", "(Z)Ljava/lang/Boolean;"); if (boolean_valueOf == NULL) return NULL; // 3. 将jboolean装箱为Boolean对象并添加到ArrayList jboolean a = JNI_TRUE; jobject boolean_obj = env->CallStaticObjectMethod(boolean_cls, boolean_valueOf, a); if (boolean_obj != NULL) { jmethodID array_list_add = env->GetMethodID(array_list_cls, "add", "(Ljava/lang/Object;)Z"); if (array_list_add != NULL) { env->CallBooleanMethod(array_list_obj, array_list_add, boolean_obj); } } // 释放局部引用,避免内存泄漏 env->DeleteLocalRef(array_list_cls); env->DeleteLocalRef(boolean_cls); env->DeleteLocalRef(boolean_obj); return array_list_obj; }
关键注意事项
- 基本类型装箱:JNI中所有需要传入Object的方法,必须使用对应包装类对象。
boolean类型通过Boolean.valueOf(boolean)静态方法完成装箱,方法签名为(Z)Ljava/lang/Boolean;。 - 方法签名匹配:调用JNI方法时必须严格匹配Java方法签名,比如ArrayList无参构造的签名是
()V,调用NewObject时不能额外传参。 - 错误检查:实际开发中要对
FindClass、GetMethodID等JNI调用的返回值做NULL检查,提前规避崩溃风险。 - 局部引用管理:JNI创建的局部引用会占用JVM内存,使用完毕后通过
DeleteLocalRef释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Taki HARBI
相关产品推荐
相关产品推荐

