如何在JNI中获取Kotlin HashMap中存储的String列表值?
JNI获取Kotlin HashMap中ArrayList值的崩溃问题解决方法
你的JNI代码存在三个核心问题导致崩溃,逐一修正即可解决:
1. 方法签名错误
HashMap的get方法签名并非(Ljava/lang/String;)[Ljava/lang/String;,原因如下:
- 泛型在JNI层面会被类型擦除,
get方法的参数实际是Object类型,参数部分签名为(Ljava/lang/Object;) get方法返回的是Object(你存储的是ArrayList对象,并非直接的字符串数组),返回值部分签名为Ljava/lang/Object;
正确的方法签名应为:(Ljava/lang/Object;)Ljava/lang/Object;
2. 参数传递错误
直接将C字符串字面量强转为jstring是无效操作,必须通过JNI的NewStringUTF方法创建合法的jstring对象。
3. 类型转换错误
HashMap中存储的是ArrayList<String>,调用get方法返回的是ArrayList对象,不能直接转为jobjectArray,需要先调用ArrayList的toArray方法将其转换为字符串数组。
修正后的完整代码
// 1. 获取HashMap类与get方法ID jclass hashMapClass = env->GetObjectClass(hm); jmethodID getMethodId = env->GetMethodID(hashMapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); // 2. 创建合法的jstring类型键值 jstring key = env->NewStringUTF("in1"); // 3. 调用get方法获取ArrayList对象 jobject arrayListObj = env->CallObjectMethod(hm, getMethodId, key); // 及时释放局部引用,避免内存泄漏 env->DeleteLocalRef(key); env->DeleteLocalRef(hashMapClass); if (arrayListObj == nullptr) { // 处理键不存在的场景 return nullptr; } // 4. 获取ArrayList类与toArray方法ID jclass arrayListClass = env->GetObjectClass(arrayListObj); jmethodID toArrayMethodId = env->GetMethodID(arrayListClass, "toArray", "()[Ljava/lang/Object;"); // 5. 调用toArray得到Object数组,再转换为String数组 jobjectArray objectArray = (jobjectArray)env->CallObjectMethod(arrayListObj, toArrayMethodId); jclass stringClass = env->FindClass("java/lang/String"); jobjectArray stringArray = (jobjectArray)env->NewObjectArray(env->GetArrayLength(objectArray), stringClass, nullptr); for (int i = 0; i < env->GetArrayLength(objectArray); i++) { jobject strObj = env->GetObjectArrayElement(objectArray, i); env->SetObjectArrayElement(stringArray, i, strObj); env->DeleteLocalRef(strObj); } // 释放剩余局部引用 env->DeleteLocalRef(arrayListClass); env->DeleteLocalRef(objectArray); env->DeleteLocalRef(arrayListObj); env->DeleteLocalRef(stringClass); // stringArray即为最终需要的字符串数组
额外注意事项
- JNI中局部引用数量有限,务必及时释放不再使用的引用,防止内存泄漏
- 若Kotlin使用
mutableMapOf等其他Map实现,核心逻辑一致,因为它们都继承自Java的Map接口 - 若无需转换为数组,也可直接调用ArrayList的
get(int)方法逐个获取元素
内容的提问来源于stack exchange,提问作者Edward Snowden
相关产品推荐
相关产品推荐

