Java 为什么幻影引用在排队时没有被清除?

Java 为什么幻影引用在排队时没有被清除?,java,garbage-collection,Java,Garbage Collection,我们可以看到,“幻影可达”与“不可达”一样不可达: 一个对象是幻影可及的,如果它既不是强的,软的,也不是弱可及的,它已经被确定,并且一些幻影引用引用它 最后,当无法通过上述任何方式访问对象时,对象是不可访问的,因此有资格进行回收 现在,从: 与软引用和弱引用不同,幻像引用在排队时不会被垃圾收集器自动清除。可通过幻象引用访问的对象将保持此状态,直到清除所有此类引用或其自身变得不可访问为止 基本原理是什么?甚至有一个吗 这是Java API怪癖的另一个典型案例吗?软引用在排队时被清除,因为软引用的主

我们可以看到,“幻影可达”与“不可达”一样不可达:

一个对象是幻影可及的,如果它既不是强的,软的,也不是弱可及的,它已经被确定,并且一些幻影引用引用它

最后,当无法通过上述任何方式访问对象时,对象是不可访问的,因此有资格进行回收

现在,从:

与软引用和弱引用不同,幻像引用在排队时不会被垃圾收集器自动清除。可通过幻象引用访问的对象将保持此状态,直到清除所有此类引用或其自身变得不可访问为止

基本原理是什么?甚至有一个吗


这是Java API怪癖的另一个典型案例吗?

软引用在排队时被清除,因为软引用的主要用途是允许缓存大型对象,而清除软引用则允许对大型缓存对象进行垃圾收集

弱引用在排队时被清除,因为弱引用的主要用途是允许引用对象而不阻止对象被垃圾收集,因此在对象排队时清除引用允许对象被垃圾收集

排队时不会清除幻影引用,因为幻影引用的一个用例是允许在垃圾收集对象之前执行清理。通过不清除引用,对象保持幻影可访问(并且不符合垃圾收集的条件),直到用户清除对该对象的幻影引用,或者幻影引用本身被垃圾收集

这就解释了,

一个对象是幻影可及的,如果它既不是强的,软的,也不是弱可及的,它已经被确定,并且一些幻影引用引用它

最后,当无法通过上述任何方式访问对象时,对象是不可访问的,因此有资格进行回收

这是JDK9中的一个例子。现在,幻影引用会像软引用和弱引用一样被清除。而相应的段落则从文件中删除

与软引用和弱引用不同,幻像引用不是 垃圾收集器在它们排队时自动清除。 可通过幻象引用访问的对象将保持这种状态 直到所有此类引用被清除或其本身成为 遥不可及


谢谢你的回答。您知道使用幻影引用的用例吗?如果已经创建了一个对象的幻影引用,但是没有对它的其他引用存在,那么通过什么方式可以存在对该对象的可访问引用?如果不存在可访问的引用,为什么不收集对象?@sbridges,引用“幻影引用的一个用例是允许在垃圾收集对象之前执行清理”。事实检查:没有这样的用例。事实上,当“引用”可用时,即使在“引用”可用之前或之后进行清理又有什么关系呢?有这样的用例。它通常与清理不由Java管理的外部资源有关。例如,在Java中执行OpenGL时,必须(像在OpenGL中一样)通过调用各种glDelete函数销毁OpenGL资源(纹理、着色器等),以释放GPU内存、句柄等。您可以手动跟踪何时需要OpenGL资源(C++风格的内存管理),也可以使用幻影引用并在资源的Java包装器不再具有强可访问性时销毁这些资源。这样,您就不必为OpenGL resourcesUpdate执行C风格的内存管理:对于Java 9,它们似乎已经改变了幻影引用的行为。在Java9之前,幻影引用通常更容易实现这一点,因为您可以访问即将被垃圾收集的对象(它在排队之前不是gc的,可以通过受保护的
referent
变量访问它,而无需重新启动它)。但在Java9中,他们似乎已经改变了这一点,因此引用对象现在在排队之前是gc’ed的。那就对了。在我的OpenGL示例中,您最好使用弱引用(也可能更好,因为弱引用比幻像引用更快进入队列)。错误报告:实际上,幻像引用在jdk 9中被垃圾收集器自动清除时。。。