2

デモコード:

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 オブジェクトを返し、ループを中断すると思いますが、このデモ コードを呼び出すと、私の考えとは異なります。

編集済み: デモ コードを変更しました。現在は動作します。

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 を割り当てるテスト オブジェクトを収集します。

4

2 に答える 2

4

変数がまだ存在しているという事実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.");
    }
}
于 2011-09-22T10:58:52.770 に答える
1

試す

test = null;

while ループの前に、テスト オブジェクトがガベージ コレクションの対象となるようにします。

于 2011-09-22T10:59:13.350 に答える