I'm new to JNI and I want to create an ArrayList<Boolean>
from the C side.
I have the following situation:
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();
}
and my cpp file is:
...
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;
}
It shows me:
#
# 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
I'm pretty sure that the error comes from env->CallBooleanMethod(java_util_object, java_add_method, a);
because the add method requires an object, and a
is jboolean.
I tried to cast the a
variable but it didn't work as well.
CodePudding user response:
ArrayList<Boolean>
is the same as just ArrayList
. At runtime, the <Boolean>
doesn't exist. This is called "type erasure".
The next thing to notice is that you did not try to add a Boolean
(a kind of Object
) but a primitive boolean
. This probably gets interpreted as an object pointer and since it's not null it's the address of an Object
- but true
(the number 1) isn't a valid address of anything, and when the JVM dereferences it it crashes.
You need to get the static field Boolean.TRUE
and add that to the ArrayList
.
CodePudding user response:
I found a way to instantiate a java Boolean Object from c using
Boolean.valueOf()
function.
I first get staticMethodId and then use it to create jobject
and use the same object in the add method as follow:
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;
}