As I understand working use case of detecting when object was collected and memory already free for weak/soft references it polling this queue and when reference appear in queue we can be sure that memory free.
WeakReference ref = new WeakReference (new Object())
Why cannot I poll ref
and check that it became null ?
P.S.
according the link provided in comment:
If the garbage collector discovers an object that is weakly reachable,
the following occurs:
1.The WeakReference object's referent field is set
to null, thereby making it not refer to the heap object any longer.
2.The heap object that had been referenced by the WeakReference is
declared finalizable.
3.When the heap object's finalize() method is run
and its memory freed, the WeakReference object is added to its
ReferenceQueue, if it exists.
Thus if this article write truth and these steps ordered weakreference becomes null after step but object adds to the queue only on 3th step.
Is it truth?
Is it cause why?
Lets research code:
working canonical example:
public class TestPhantomRefQueue {
public static void main(String[] args)
throws InterruptedException {
Object obj = new Object();
final ReferenceQueue queue = new ReferenceQueue();
final WeakReference pRef =
new WeakReference(obj, queue);
obj = null;
new Thread(new Runnable() {
public void run() {
try {
System.out.println("Awaiting for GC");
// This will block till it is GCd
Reference prefFromQueue;
while (true) {
prefFromQueue = queue.remove();
if (prefFromQueue != null) {
break;
}
}
System.out.println("Referenced GC'd");
System.out.println(pRef.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// Wait for 2nd thread to start
Thread.sleep(2000);
System.out.println("Invoking GC");
System.gc();
}
}
this code output:
Awaiting for GC
Invoking GC
Referenced GC'd
null
Ok, I understand why it does work.
Lets change code a bit:
public class TestPhantomRefQueue {
public static void main(String[] args)
throws InterruptedException {
Object obj = new Object();
final ReferenceQueue queue = new ReferenceQueue();
final WeakReference pRef =
new WeakReference(obj, queue);
obj = null;
new Thread(new Runnable() {
public void run() {
try {
System.out.println("Awaiting for GC");
while (true) {
if (pRef.get() == null) {
Thread.sleep(100);
break;
}
}
System.out.println("Referenced GC'd");
System.out.println(pRef.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// Wait for 2nd thread to start
Thread.sleep(2000);
System.out.println("Invoking GC");
System.gc();
}
}
this variant hangs in while loop and output:
Awaiting for GC
Invoking GC
Please explain this behaviour.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…