JVM学习-深入理解Java虚拟机代码实践问题
《深入理解java虛擬機》第3版
代碼清單3-7 新生代Minor GC
private static final int _1MB = 1024 * 1024; /** * VM參數: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 */ public static void testAllocation() {byte[] allocation1, allocation2, allocation3, allocation4;allocation1 = new byte[2 * _1MB];allocation2 = new byte[2 * _1MB];allocation3 = new byte[2 * _1MB];allocation4 = new byte[4 * _1MB]; // 出現一次Minor GC }使用JDK1.8做驗證,發現和書中描述不一致。
?
考慮前面版本成書較早,可能基于較早的jre版本運行。
首先考慮的原因是默認的垃圾收集器不同,JDK8默認為Parallel Scavenge+Parall Old組合 跟作者的JDK6使用的Serial+Serial Old組合的算法不一致。
因此增加參數:-XX:+UseSerialGC 后再次測試,還是相同結果。
然后想到新生代對象晉升老年代的規則之一:大對象直接分配到老年代。
因此增加參數:-XX:PretenureSizeThreshold=10485760 后測試,還是沒有達到預期。
后來想到,老年代的4M不一定就是一個對象的4M,也可能是2個2M的對象。于是想到通過打斷點運行,并配合可視化工具 visualvm 來動態觀察JVM堆內存各區的變化情況。
?通過分析知道,JVM初始化時有部分對象影響了測試結果。即初始化時對象大小超過2M,到運行allocation1、allocation2后,在allocation3對象分配時Eden區已經不夠存放,因此在預期之前發生了MinorGC。因此在運行目標代碼前增加一行
System.gc();解決了困惑。
?可能有人會問,原來那個正好40%,即4M,而我這邊斷點之后其實不是4M,而是6M+?這個猜測是因為斷點導致一些對象被引用著而存活下來了,而不打斷點運行時直接被當垃圾回收了。
結束。
總結
以上是生活随笔為你收集整理的JVM学习-深入理解Java虚拟机代码实践问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 系统 hosts 文件修改工具
- 下一篇: 笔记:Java虚拟机运行时数据区