可以在(本机)调用中间的对象上调用终结器吗? [英] Can a finalizer be called on an object that is in the middle of a (native) call?

查看:71
本文介绍了可以在(本机)调用中间的对象上调用终结器吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们看到了一个奇怪的AddressSanitizer(clang/C ++)释放后使用堆"违规,这可能与终结器的极端情况有关.

We're seeing a weird AddressSanitizer (clang/C++) "heap-use-after-free" violation that might relate to a finalizer corner case.

比方说,Java对象OBJ拥有本机资源X的句柄.以前创建OBJ的线程现在正在OBJ.method()上进行调用,该调用将调用(静态)本机方法staticMethod( X),其中使用了X.

Let's say, a Java object OBJ has a handle to to a native resource X. A thread that created OBJ before, is now making a call on OBJ.method(), which calls into a (static) native method staticMethod(X), in which X is used.

现在,几乎在同一时间,我们看到一个线程正在删除本机资源X.我们强烈假设这是由终结器调用OBJ.finalize()触发的,它执行删除X".

Now, at more or less the same time, we're seeing a thread deleting the native resource X. We strongly assume that this triggered by the finalizer calling OBJ.finalize(), which does "delete X".

这对于终结器来说是正确的事吗?

Is this a valid thing to do for a finalizer?

(OpenJDK 8)

(OpenJDK 8)

推荐答案

一种安全的方法似乎是使用非静态本机JNI方法.

A safe way to do this seems to be using non-static native JNI methods.

在C/C ++中,静态JNI方法签名看起来像这样:

In C/C++, a static JNI method signature looks something like this:

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

请注意第二个参数jclass type传递Java类的JNI表示形式.

Note the second parameter jclass type passing the JNI representation of a Java class.

但是,非静态JNI方法改为接受当前的Java实例对象(this)并看起来像这样:

A non-static JNI method, however, accepts the current Java instance object (this) instead and looks like this:

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

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

Background: The VM seems to optimize garbage collection quite aggressively. A thread still running a (non-static) method but calling only into a native static method does NOT prevent the object from being freed. If the JNI method is non-static however, this tells the VM that the Java object is still being referenced. Then, only once the the call returns this native reference to the object is cleared. Thus, no finalizer is allowed to run before that.

这篇关于可以在(本机)调用中间的对象上调用终结器吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆