WeakHashMap遇到一些麻烦.
考虑这个示例代码:
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());
此代码工作.在循环中,我正在创建对象.当发生次要的GC时,地图大小在第1360次迭代时等于1.一切都OK.
现在我评论这一行:
//anObject = null;
我期望有一个OutOfMemoryError,因为mapSize总是等于2.但是在26XXX的迭代中,一个完整的GC发生,地图大小等于0.我不明白为什么?
我认为地图不应该被清除,因为还有很强的引用对象.
解决方法
即时编译器分析代码,看到在循环之后没有使用anObject和anOtherObject,并将它们从本地变量表中删除或将其设置为null,同时循环仍在运行.这被称为OSR编译.
之后,GC收集字符串,因为没有强烈的引用.
如果在循环后使用anObject,你仍然会得到一个OutOfMemoryError.
更新:您将在我的博客中找到关于OSR compilation的更详细的讨论.