Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are WeakHashMap cleared during a full GC?

I encountered some troubles with WeakHashMap.

Consider this sample code:

List<byte[]> list = new ArrayList<byte[]>();

Map<String, Calendar> map = new WeakHashMap<String, Calendar>();
String anObject = new String("string 1");
String anOtherObject = new String("string 2");

map.put(anObject, Calendar.getInstance());
map.put(anOtherObject, Calendar.getInstance());
// In order to test if the weakHashMap works, i remove the StrongReference in this object
anObject = null;
int i = 0;
while (map.size() == 2) {
   byte[] tab = new byte[10000];
   System.out.println("iteration " + i++ + "map size :" + map.size());
   list.add(tab);
}
System.out.println("Map size " + map.size());

This code works. Inside the loops, i'm creating object.When a minor GC occurs, the map size is equal to 1 at the 1360th iteration. All is OK.

Now when i comment this line:

//anObject = null; 

I expect to have an OutOfMemoryError because the mapSize is always equal to 2. However at the 26XXX th iteration, a full GC occurs and the map size is equal to 0. I dont understand why?

I thought that the map shouldn't have cleared because there are also strong references to both objects.

like image 773
Slade Avatar asked Jan 11 '12 11:01

Slade


People also ask

What is true about WeakHashMap?

Simply put, the WeakHashMap is a hashtable-based implementation of the Map interface, with keys that are of a WeakReference type. An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use, meaning that there is no single Reference that point to that key.

Where do I use WeakHashMap?

If you have some objects that are reused often in your application, and their construction is expensive, and there are too many of them to keep them all in memory - - you use WeakHashMap. Put there the object which is not currently used. When this object is needed - get it out of the map.


1 Answers

The just-in-time compiler analyzes the code, sees that anObject and anOtherObject are not used after the loop, and removes them from the local variable table or sets them to null, while the loop is still running. This is called OSR compilation.

Later the GC collects the strings because no strong references to them remain.

If you used anObject after the loop you'd still get an OutOfMemoryError.

Update: You'll find a more detailed discussion about OSR compilation in my blog.

like image 115
Joni Avatar answered Sep 18 '22 12:09

Joni