Ecco il mio codicePerché non posso ottenere PhantomReference da ReferenceQueue per un oggetto finalizzabile?
public class FinalizableObject {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize() invoked for " + this);
super.finalize();
}
}
public class Main {
private static void test() throws InterruptedException {
ReferenceQueue<FinalizableObject> rq = new ReferenceQueue<FinalizableObject>();
FinalizableObject obj = new FinalizableObject();
PhantomReference<FinalizableObject> pr1 = new PhantomReference<FinalizableObject>(obj, rq);
obj = null;
System.gc();
Reference<? extends Object> ref = rq.remove();
System.out.print("remove " + ref + " from reference queue\n");
}
public static void main(String[] args) {
try {
test();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
E 'molto strano, rq.remove() sarà bloccato per sempre. Perché il riferimento fantasma dell'oggetto finalizzabile non può essere inserito nella coda di riferimento? È stato raccolto GC?
Grazie mille.
Conosco FinalizerReferenceQueue e FinalizerDeamon, 2 volte GC può raccogliere completamente un oggetto finalizzabile. Ma non riesco a capire il motivo per cui 100 volte il GC attiverà il ritiro (anche 20 volte il GC non può attivare l'accodamento).
D'altra parte, se sostituisco PhantomReference con WeakReference, è possibile rimuovere il riferimento molto rapidamente.
–
@DevboardFan Questo perché per invocare il metodo 'finalize()' non banale, JVM costruisce Finalizer-Thread speciale, che deve anche essere raccolto e completato. – Andremoniy
Grazie mille! –