java - 为什么 PhantomReference 不起作用?

标签 java phantom-reference

演示代码:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Object test = new Object();
        ReferenceQueue<Object> q = new ReferenceQueue<Object>();
        PhantomReference<Object> p = new PhantomReference<Object>(test, q);
        Object lock = new Object();
        while (true) {
            synchronized (lock) {
                                 //q.poll() is null always,why?
                if (q.poll() != null) {
                    break;
                }
                //System.gc();
                lock.wait();
            }
        }
        System.out.println(1111111);
    }
}

我测试了代码,但它总是死循环。 代码(System.out.println(1111111);)无法执行,q.poll()返回null。

我认为如果测试对象被GC删除,q.poll()将返回p对象,然后中断循环,但是调用这个演示代码,这并不像我的想法

编辑: 我修改了demo代码,现在可以运行了。

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Object test = new Object();
        ReferenceQueue<Object> q   = new ReferenceQueue<Object>();
        PhantomReference<Object> p = new PhantomReference<Object>(test, q);
        Object lock = new Object();
        while (true) {
            synchronized (lock) {
                if (q.poll() != null) {
                    break;
                }
                test = null; //it is important  
                System.gc();
                lock.wait(100);//should not lock.wait()
            }
        }
        System.out.println(1111111);
    }
}

正如sb所说,语句(test=null)是关键。GC收集分配null的测试对象。<​​/p>

最佳答案

test 变量仍然存在的事实意味着 GC 永远不会收集它引用的对象...我相信 JVM 不会收集局部变量引用的任何内容,即使方法的其余部分永远不会引用局部变量。

(另外,当没有任何东西调用 lock.pulse() 时,还不清楚为什么要使用 lock.wait()。)

这是适合我的代码:

import java.lang.Thread;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object test = new Object();
        ReferenceQueue<Object> q = new ReferenceQueue<Object>();
        PhantomReference<Object> p = new PhantomReference<Object>(test, q);
        Object lock = new Object();
        while (true) {
            System.out.println("Checking queue...");
            if (q.poll() != null) {
                break;
            }
            System.out.println("Still polling...");
            System.gc();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                System.out.println("Interrupted!");
                break;
            }
            // Make the object garbage...
            test = null;
        }
        System.out.println("Finished.");
    }
}

关于java - 为什么 PhantomReference 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7513571/

相关文章:

java - 为什么我们必须手动清除 PhantomReference?

java - 如何判断 Java import 语句何时使用通配符匹配?

java - 无法识别 Eclipselink 实体

java - Java终结器的替代品

java - GC 不会通过虚拟引用收集类的内部字段

java - 何时在 Java 中使用弱引用和虚引用

java - 我将如何打破程序中这一部分的循环?

java - 如何为在线交易创建支付网关?

java - 干扰线程

Java:强/软/弱/幻像引用之间的区别