2回复
3年前
为什么 JNI 的 FindClass 方法有奇怪的副作用?
我在用 JNI 的时候遇到了一个很奇怪的问题,有人能帮忙分析一下到底是怎么回事吗
如果我按原样运行下面的代码,会看到这个:
(a) 7fb6f022faf0 7fb6f022fb00 0
(b) 7fb6f022faf8 7fb6f022fb00 1
如果我取消注释标记为 // (*) 的行,那么我会看到:
(a) 7f6ce822faf0 7f6ce822fb08 1
(b) 7f6ce822fb00 7f6ce822fb08 1
注释掉 (*) 行(应该是空操作!)后,用 Class.equals 方法发现 Integer.class 的一个实例与 Integer.class 的另一个实例不相等。 取消注释该行,java.lang.Integer 在 test1 方法中被查找了两次而不是一次,并且由于某种原因,现在发现 Integer.class 的两个实例是相等的! (这是在 JDK 16 上。)
完全搞不懂这是怎么回事
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));
}
1468 阅读