我唯一知道的PhantomReference是,
get()方法,它将始终返回null而不是对象.有什么用?PhantomReference,可以确保无法从finalize方法中复活对象.但是这个概念/类的用途是什么?
你有没有在你的任何项目中使用过这个,或者你有任何我们应该使用它的例子吗?
我们可以看到"幻影可达"与"无法访问"一样无法访问:§
如果一个物体既不是强烈的,柔和的,也不是微弱的可触及的,那么该物体是幻影可达的,它已被最终确定,并且一些幻象参考指的是它.
最后,如果无法通过上述任何方式访问某个对象,则该对象无法访问,因此有资格进行回收.
现在,来自:http://download.oracle.com/javase/6/docs/api/java/lang/ref/PhantomReference.html
与软引用和弱引用不同,垃圾收集器在排队时不会自动清除幻像引用.通过幻像引用可访问的对象将保持不变,直到所有此类引用都被清除或自身无法访问.
基本原理是什么?还有一个吗?
这是Java API怪癖的另一个典型案例吗?
据我所知,静态字段(以及线程,局部变量和方法参数,JNI引用)充当GC根。
我无法提供可以确认这一点的链接,但是我已经阅读了很多文章。
为什么非静态字段不能充当GC根?
我一直在阅读有关PhantomReference https://www.baeldung.com/java-phantom-reference的文章,并在此处找到了简化的示例代码:
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
Object object = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<>(object, referenceQueue);
object = null;
System.gc();
Thread.sleep(1_000);
System.out.println("isEnqueued() after GC: " + phantomReference.isEnqueued());
Reference reference = referenceQueue.poll();
if(reference != null) {
System.out.println("isEnqueued() after poll(): " + phantomReference.isEnqueued());
}
}
Run Code Online (Sandbox Code Playgroud)
输出如下:
isEnqueued() after GC: true
isEnqueued() after poll(): false
Run Code Online (Sandbox Code Playgroud)
因此,一切工作都按预期进行,将对对象的强引用设置为null(GC会将其检测到)并将幻像引用添加到队列中。
现在在那篇文章中,他们说:“垃圾收集器在执行其引用的finalize方法之后,将一个幻像引用添加到引用队列。这意味着该实例仍在内存中。”
所以我想进行测试并覆盖finalize方法,例如:
Object object = new Object() {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize()"); …Run Code Online (Sandbox Code Playgroud) PhantomReference java 8及以下版本的java doc如下所示:
Phantom 引用对象,在收集器确定它们的引用对象可能会被回收后入队。幻像引用最常用于以比 Java 终结机制更灵活的方式调度预检清理操作。如果垃圾收集器在某个时间点确定幻像引用的所指对象是幻像可达的,那么在那个时候或稍后的某个时间它将将该引用加入队列。
为了确保可回收对象保持如此,可能无法检索幻像引用的所指对象:幻像引用的 get 方法始终返回 null。
与软引用和弱引用不同,幻像引用在入队时不会被垃圾收集器自动清除。可通过幻像引用访问的对象将保持不变,直到所有此类引用都被清除或自身变得无法访问
PhantomReference java 9及更高版本的java doc如下所示:
Phantom 引用对象,在收集器确定它们的引用对象可能会被回收后入队。虚拟引用最常用于安排事后清理操作。假设垃圾收集器在某个时间点确定某个对象是虚拟可达的。届时,它将自动清除对该对象的所有幻影引用以及对该对象可从中访问的任何其他幻影可访问对象的所有幻影引用。同时或稍后它会将那些注册到引用队列的新清除的幻像引用加入队列。
为了确保可回收对象保持如此,可能无法检索幻像引用的所指对象:幻像引用的 get 方法始终返回 null。
java 9中的PhantomReference行为是否发生了变化?还是只是 Java 创始人重新思考了该课程的奉献精神?
我试着理解课堂 ReferenceQueue
它是可选的构造函数参数
SoftReference
Run Code Online (Sandbox Code Playgroud)
和
WeakReference
Run Code Online (Sandbox Code Playgroud)
它也是 的强制性参数PhantomReference。
根据我读过的信息,我可以写一些论文
a) 对于 PhantomReference 方法 get 总是返回 null
b)
对于 Phantom 引用:
1. gc 检测到该对象可以从内存中删除
2. 对放入 ReferenceQueue 的对象的引用,
当我们调用 clear 或 link to reference from queue 时无法访问并且 gc 看到 3. finalize 方法调用
4.
为弱/软引用释放内存:
1. gc 检测到该对象可以从内存中删除
2. 终结方法调用
3. 释放内存
4. 对放入队列的对象的引用
XXXReference构造函数?PhantomReference没有没有构造函数ReferenceQueue?