开发者

why PhantomReference does not work?

Demo code:

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);
    }
}

I tested the code,but it always is dead loop. The code (System.out.println(1111111);) can not execute,q.poll() reurn null.

I think if test object is removed by GC,q.poll() will return p object,then break loop,but invoke this demo code,it is not like my thought

Edited: I modify the demo code,it can work now.

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()
         开发者_如何学C   }
        }
        System.out.println(1111111);
    }
}

AS sb says,the statement( test=null) is key.GC collect test object that assign null.


The fact that the test variable is still present means the GC will never collect the object it refers to... I believe JVMs don't collect anything that a local variable refers to even if the local variable is never referred to in the rest of the method.

(Also, it's not clear why you're using lock.wait() when nothing is calling lock.pulse().)

Here's code which works for me:

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.");
    }
}


Try

test = null;

before your while loop, so that the test object is eligible for garbage collection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜