Sla*_*ade 11 java jit weak-references
我遇到了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());
Run Code Online (Sandbox Code Playgroud)
这段代码有效.在循环内部,我正在创建对象.当发生次要GC时,映射大小在第1360次迭代时等于1.一切都好.
现在,当我评论这一行:
//anObject = null;
Run Code Online (Sandbox Code Playgroud)
我希望有一个OutOfMemoryError,因为mapSize总是等于2.但是在第26XXX次迭代时,发生了一个完整的GC并且地图大小等于0.我不明白为什么?
我认为地图不应该已经清除,因为还有对这两个对象的强引用.
挖掘的部分揭示了JLS第12.6.1节中明确涵盖的内容:
可以设计优化程序的转换,以减少可达到的对象的数量,使其少于可以被认为可达的对象的数量.例如,编译器或代码生成器可以选择设置将不再用于null的变量或参数,以使得此类对象的存储可能更快地被回收.
(Bolding是我的补充.)
http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6.1
所以从本质上讲,JIT可以随时删除强引用,如果它能够解决它们永远不会被再次使用的话 - 这正是这里发生的事情.
这是一个很好的问题,并且可以很容易地显示一个非常好的益智游戏,因为一个对象似乎在范围上有很强的引用,并不一定意味着它没有被垃圾收集.继续这一点意味着你明确地无法保证什么时候终结器会运行,这甚至可能是在对象仍然在范围内的情况下!
例如:
List<byte[]> list = new ArrayList<byte[]>();
Object thing = new Object() {
protected void finalize() {
System.out.println("here");
}
};
WeakReference<Object> ref = new WeakReference<Object>(thing);
while(ref.get()!=null) {
list.add(new byte[10000]);
}
System.out.println("bam");
Run Code Online (Sandbox Code Playgroud)
以上是一个更简单的示例,显示对象最终完成并首先GC,即使引用thing仍然存在(此处打印,然后是bam.)
只是为Joni Salonen和berry120的优秀答案添加一些东西.可以证明,JIT实际上负责"变量移除",只需将其关闭即可-Djava.compiler=NONE.一旦你把它关掉,你就得到了OOME.
如果我们想知道引擎盖下发生了什么,该选项会XX:+PrintCompilation显示JIT活动.将它与问题中的代码一起使用我们获得的输出如下:
1 java.lang.String::hashCode (64 bytes)
2 java.lang.String::charAt (33 bytes)
3 java.lang.String::indexOf (151 bytes)
4 java.util.ArrayList::add (29 bytes)
5 java.util.ArrayList::ensureCapacity (58 bytes)
6 ! java.lang.ref.ReferenceQueue::poll (28 bytes)
7 java.util.WeakHashMap::expungeStaleEntries (125 bytes)
8 java.util.WeakHashMap::size (18 bytes)
1% WeakHM::main @ 63 (126 bytes)
Map size 0
Run Code Online (Sandbox Code Playgroud)
最后一次编译(使用@标志)是OSR(On Stack Replacement)编译(有关详细信息,请查看https://gist.github.com/rednaxelafx/1165804#osr).简单来说,它使VM能够在运行时替换方法,并用于提高陷入循环的Java方法的性能.我猜想在触发这个编译之后,JIT会删除不再使用的变量.
| 归档时间: |
|
| 查看次数: |
1311 次 |
| 最近记录: |