如何使地址 return 由 JNI FindClass return 编辑总是相同的地址

How to make address returned by JNI FindClass return always the same address

在我的 C 程序中,我有以下代码:

jclass class;
jmethodID method;


class = (*env)->FindClass(env, "java/lang/Short");
method = (*env)->GetMethodID(env, class, "<init>", "(S)V");
printf("First: class=%p * method=%p\n", class, method);


class = (*env)->FindClass(env, "java/lang/Short");
method = (*env)->GetMethodID(env, class, "<init>", "(S)V");
printf("Second: class=%p * method=%p\n", class, method);

当我编译程序(在 GCC 中)并 运行 它时,它给出以下输出:

First: class=0x7f55ac089450 * method=0x7f55ac0d99b8

Second: class=0x7f55ac089458 * method=0x7f55ac0d99b8

正如你所看到的,class的地址在每次调用FindClass时都是不同的。我认为 class 的地址是静态的,它在我们程序的生命周期内不会改变。事实上,当人们阅读 IBM 的这篇关于如何使用 JNI (https://developer.ibm.com/languages/java/articles/j-jni/#notc) 优化 C 代码的著名文章时,他们说要缓存 FindClass 返回的值(所以人们会期望它不会改变)。但是,如果您稍后在 JNI 函数调用中使用这个缓存值,它会使您的 C 程序崩溃(因为它使用了 Java class 的错误地址)。

另一个奇怪的事情是,当缓存 FindClass 为 class java/lang/Integer 返回的值时(而不是上面发布的 java/lang/Short),然后使用这个稍后缓存的值一切正常并按预期工作(即没有崩溃)。

什么 FindClass returns 是 a local reference 一个 Java Class 对象。

在您的示例中,您获得了两个单独的引用 - 但它们可能都引用了同一个对象。

考虑如果行为符合您的预期并且您对两个 FindClass 调用获得相同的参考会发生什么:

first = (*env)->FindClass(env, "java/lang/Short");
second = (*env)->FindClass(env, "java/lang/Short");
(*env)->DeleteLocalRef(env, first);
method = (*env)->GetMethodID(env, second, "<init>", "(S)V");  // OOPS! this reference may no longer be valid

实际上,上面的代码可以正常工作,因为 firstsecond 将是对 Class<Short>.

的单独引用