почему PhantomReference не работает? - PullRequest
2 голосов
/ 22 сентября 2011

Демонстрационный код:

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 () возвращает ноль.

Я думаю, если тестовый объект будет удален с помощью GC, q.poll () вернет объект p, затем прервите цикл, но вызовите этот демонстрационный код, это не похоже на мою мысль

Отредактировано: я изменяю демонстрационный код, теперь он может работать.

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) является key.GC собирает тестовый объект, которому присваивается значение null.

Ответы [ 2 ]

4 голосов
/ 22 сентября 2011

Тот факт, что переменная test все еще присутствует, означает, что GC никогда не будет собирать объект, на который он ссылается ... Я считаю, что JVM не собирают ничего, на что ссылается локальная переменная, даже если локальная переменная никогда не указывается в остальной части метода.

(Кроме того, неясно, почему вы используете lock.wait(), когда ничего не звонит lock.pulse().)

Вот код, который работает для меня:

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.");
    }
}
1 голос
/ 22 сентября 2011

Попробуйте

test = null;

перед циклом while, чтобы тестовый объект имел право на сборку мусора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...