java - 是否可以在( native )调用过程中的对象上调用终结器?

标签 java java-native-interface finalizer

我们发现一个奇怪的 AddressSanitizer (clang/C++)“释放后堆使用”违规,可能与终结器极端情况有关。

假设一个 Java 对象 OBJ 有一个指向 native 资源 X 的句柄。之前创建 OBJ 的线程现在正在调用 OBJ.method(),该方法调用一个(静态) native 方法 staticMethod( X),其中使用X。

现在,我们几乎同时看到一个线程正在删除 native 资源 X。我们强烈假设这是由调用 OBJ.finalize() 的终结器触发的,它确实“删除了 X”。

对于终结器来说,这是有效的做法吗?

(OpenJDK 8)

最佳答案

一种安全的方法似乎是使用非静态 native JNI 方法。

在 C/C++ 中,静态 JNI 方法签名如下所示:

extern "C" JNIEXPORT jobject JNICALL
Java_com_example_MyClass_myMethod(JNIEnv* env, jclass type, jlong handle);

注意第二个参数jclass type传递Java类的JNI表示。

但是,非静态 JNI 方法接受当前 Java 实例对象 (this),如下所示:

extern "C" JNIEXPORT jobject JNICALL
Java_com_example_MyClass_myMethod(JNIEnv* env, jobject thisObj, jlong handle);

背景:虚拟机似乎非常积极地优化垃圾收集。仍在运行(非静态)方法但仅调用 native 静态方法的线程不会阻止释放对象。然而,如果 JNI 方法是非静态的,这会告诉 VM Java 对象仍在被引用。然后,只有当调用返回时,该对象的 native 引用才会被清除。因此,在此之前不允许运行任何终结器。

关于java - 是否可以在( native )调用过程中的对象上调用终结器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47532395/

相关文章:

java - 将 Map<String,Object> 转换为 JSON 并返回 Map

java - 有没有什么方法可以参数 Jess,使其在同一规则中永远不会有太多具有不同名称的变量?

java - JNI : Can not get array length

android - 在 jni android 中返回字节数组?

c# - 即使使用 CriticalFinalizerObject,也不会在未处理的异常后调用终结器

java - 最终确定期间对对象的引用

Java Array 使用方法对 String 和 Int 进行排序

java - 如何更改 Android Dev 的 HelloFormStuff 中 RadioGroup 小部件的显示顺序?

java - JNI 调用 C 函数调用其他文件中的其他函数

Java GC 问题 : How could an object become unreachable while one of its methods is still being executed?