【问题标题】:How to make address returned by JNI FindClass return always the same address如何使 JNI FindClass 返回的地址始终返回相同的地址
【发布时间】:2021-02-20 02:17:52
【问题描述】:

在我的 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

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

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

【问题讨论】:

  • 什么保证你拨打FindClass时地址是一样的?除非short-我的意思是int-的直接值相同,否则我不会期望这一点。

标签: java c java-native-interface


【解决方案1】:

FindClass 返回的是 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&lt;Short&gt;

【讨论】:

  • 完美!通过阅读您的解决方案和您发送链接的页面,我设法解决了这个问题!
猜你喜欢
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 2017-12-14
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
相关资源
最近更新 更多