I have encountered a very strange issue with JNI. Can anybody please help me understand what is wrong here?
If I run the code below as-is, I see:
(a) 7fb6f022faf0 7fb6f022fb00 0
(b) 7fb6f022faf8 7fb6f022fb00 1
If I uncomment the line marked // (*), then I get:
(a) 7f6ce822faf0 7f6ce822fb08 1
(b) 7f6ce822fb00 7f6ce822fb08 1
With the (*) line commented out (which should be a no-op!), one instance of Integer.class is found to be unequal to another instance of Integer.class, using the Class.equals method. With the line uncommented, java.lang.Integer is looked up twice rather than once in the test1 method, and for some reason now the two instances of Integer.class are found to be equal! (This is on JDK 16.)
What the heck? I don't understand this at all...
pkg/Test.java:
package pkg;
public class Test {
public static native void test0();
public static native void test1(Object... args);
public static void main(String[] args) throws Exception {
test0();
test1(7);
}
}
test.c:
#include <jni.h>
#include <stdio.h>
jclass Integer_class_0;
JNIEXPORT void JNICALL Java_pkg_Test_test0(JNIEnv *env, jclass ignored) {
Integer_class_0 = (*env)->FindClass(env, "java/lang/Integer");
}
JNIEXPORT void JNICALL Java_pkg_Test_test1(JNIEnv *env, jclass ignored,
jobjectArray args) {
//(*env)->FindClass(env, "java/lang/Integer"); // (*)
jobject arg = (*env)->GetObjectArrayElement(env, args, 0);
jclass arg_type = (*env)->GetObjectClass(env, arg);
jclass Integer_class_1 = (*env)->FindClass(env, "java/lang/Integer");
jclass cls_class = (*env)->FindClass(env, "java/lang/Class");
jmethodID cls_equals_methodID =
(*env)->GetMethodID(env, cls_class, "equals", "(Ljava/lang/Object;)Z");
printf("(a) %lx %lx %d\n", Integer_class_0, Integer_class_1,
(*env)->CallBooleanMethod(env,
Integer_class_0, cls_equals_methodID, Integer_class_1));
printf("(b) %lx %lx %d\n", arg_type, Integer_class_1,
(*env)->CallBooleanMethod(env,
arg_type, cls_equals_methodID, Integer_class_1));
}