As pointed out by others, there is no guaranty that System.gc()
performs an actual garbage collection. Neither is a garbage collection cycle guaranteed to actually collect a particular unreachable object.
But in your specific setup, it seems that System.gc()
is sufficient to collect the object, as determined by your WeakReference
example. But clearing a weak reference is not the same as enqueuing the reference, to allow the WeakHashMap
to perform its cleanup. As explained in this answer, the cleanup of the WeakHashMap
relies on the key reference to be enqueued, which will be checked each time you’re invoking a method on it, which is the subsequent map.size()
invocation in your example.
As the documentation of WeakReference
specifies:
Suppose that the garbage collector determines at a certain point in time that an object is weakly reachable. At that time it will atomically clear all weak references to that object and all weak references to any other weakly-reachable objects from which that object is reachable through a chain of strong and soft references. At the same time it will declare all of the formerly weakly-reachable objects to be finalizable. At the same time or at some later time it will enqueue those newly-cleared weak references that are registered with reference queues.
Note how clearing happens “at that time” whereas enqueuing will happen “at the same time or at some later time”.
In case of HotSpot JVM/OpenJDK, enqueuing happens asynchronously after the garbage collection and your main thread seems to run too fast, so the key reference has not been enqueued yet.
Inserting a small pause may cause the example program to succeed in typical environments:
import java.util.WeakHashMap;
public class Main2 {
public static void main(String[] args) throws InterruptedException{
String name = new String("ltt");
WeakHashMap<String, Integer> map = new WeakHashMap<>();
map.put(name, 18);
System.out.println(map.size()); // 1
name = null;
System.gc();
Thread.sleep(10);
System.out.println(map.size()); // 0
}
}
Of course, this doesn’t change the fact that this is neat for testing, but not a guaranteed behavior, so you shouldn’t write production code relying on it.
System.gc()
does not force a garbage collection to occur. – Tuscarora