如何在<Boolean> JNI java 中返回 ArrayList?



我是JNI的新手,我想从c++端创建一个ArrayList<Boolean>

我有以下情况:

import java.util.ArrayList;
public class createArrayJNI {
static {
System.loadLibrary("libnative");
}

public static void main(String[] args) {
createArrayJNI jni =  new createArrayJNI();
ArrayList<Boolean> array = jni.creatArray();
System.err.println(array);
}
public native ArrayList<Boolean> creatArray();
}

和我的CPP文件是:

...
JNIEXPORT jobject JNICALL Java_createArrayJNI_creatArray
(JNIEnv *env, jobject thisObject) {
jclass java_util_class = env->FindClass("java/util/ArrayList");
jmethodID java_util_method_constructor = env->GetMethodID(java_util_class, "<init>", "()V");
jmethodID java_add_method = env->GetMethodID(java_util_class, "add", "(Ljava/lang/Object;)Z");
jobject java_util_object = env->NewObject(java_util_class, java_util_method_constructor, "");
jboolean a = true;
env->CallBooleanMethod(java_util_object, java_add_method, a);

return java_util_object;
}

它告诉我:

# 
# A fatal error has been detected by the Java Runtime Environment:
# 
# SIGSEGV (0xb) at pc=0x00000001099110ac, pid=24207, tid=4355
# 
# JRE version: OpenJDK Runtime Environment Homebrew (19.0.1) (build 19.0.1)
# Java VM: OpenJDK 64-Bit Server VM Homebrew (19.0.1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# V  [libjvm.dylib+0x1f10ac]  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<598116ull, G1BarrierSet>, (AccessInternal::BarrierType)2, 598116ull>::oop_access_barrier(void*)+0xc
# 
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
# 
# An error report file with more information is saved as:
# /Users/taki/Desktop/Preparation doctorat ERM/Projects/Julia4C/hs_err_pid24207.log
# 
# If you would like to submit a bug report, please visit:
# https://github.com/Homebrew/homebrew-core/issues
# 
zsh: abort      /usr/bin/env  --enable-preview -XX:+ShowCodeDetailsInExceptionMessages -cp

我很确定这个错误来自env->CallBooleanMethod(java_util_object, java_add_method, a);,因为add方法需要一个对象,而a是jboolean。

我试图转换a变量,但它不起作用。

ArrayList<Boolean>ArrayList相同。在运行时,<Boolean>不存在。这叫做"类型橡皮擦"。

接下来要注意的是,您没有尝试添加Boolean(一种Object),而是添加了原语boolean。这可能被解释为一个对象指针,因为它不是null,它是Object的地址-但是true(数字1)不是任何东西的有效地址,当JVM取消引用它时,它会崩溃。

您需要获得静态字段Boolean.TRUE并将其添加到ArrayList

我找到了一种从c++实例化java布尔对象的方法Boolean.valueOf()函数。我首先获得staticMethodId,然后使用它来创建jobject,并在添加方法中使用相同的对象,如下所示:

JNIEXPORT jobject JNICALL Java_createArrayJNI_creatArray
(JNIEnv *env, jobject thisObject) {
std::vector<bool> cpp_vec;
cpp_vec.push_back(true);
cpp_vec.push_back(false);
cpp_vec.push_back(true);

jclass java_util_class = env->FindClass("java/util/ArrayList");
jmethodID java_util_method_constructor = env->GetMethodID(java_util_class, "<init>", "()V");
jmethodID java_add_method = env->GetMethodID(java_util_class, "add", "(Ljava/lang/Object;)Z");

jobject java_util_object = env->NewObject(java_util_class, java_util_method_constructor, "");

jclass bool_class = env->FindClass("java/lang/Boolean");
jmethodID bool_init = env->GetStaticMethodID(bool_class, "valueOf", "(Z)Ljava/lang/Boolean;");

for (int i=0; i< cpp_vec.size(); i++){
jboolean curr_element = cpp_vec[i];
jobject bool_object = env->CallStaticObjectMethod(bool_class, bool_init, (jboolean) cpp_vec[i]);
if (bool_object == NULL){
std::cout << "Cannot instantiate the Boolean object";
return NULL;
} 
env->CallBooleanMethod(java_util_object, java_add_method, bool_object);
}
return java_util_object;
}

最新更新