JVM:GC日志解读
-
深入理解Java虛擬機
- [JVM]Java內存區域與垃圾收集 - 思維導圖
- [JVM]類加載機制 - 思維導圖
- [JVM]OOM實例分析
- [JVM]理解Class文件(1):手動解析常量池
- [JVM]理解GC日志
- [JVM]理解Class文件(2)
1. 輸出GC日志
通過閱讀GC日志,我們可以了解Java虛擬機內存分配與回收策略。
先來看一個簡單的示例,通過設置VM參數"XX:+PrintGCDetails"就可以打印出GC日志
-
PSYoungGen
PS是Parallel Scavenge收集器的縮寫,它配套的新生代稱為PSYoungGen,新生代又分化eden space、from space和to space這三部分 -
** ParOldGen**
Parallel Scavenge收集器配套的老年代 -
Metaspace
Parallel Scavenge收集器配套的永久代 -
total & used
總的空間和用掉的空間
2. GC日志分析
2.1 新生代Minor GC
先來回顧下垃圾回收算法,通常新生代按照8:1:1(eden space + survivor from space + survivor to space)進行內存劃分,新生產的對象會被放到eden space,當eden內存不足時,就會將存活對象移動到survivor區域,如果survivor空間也不夠時,就需要從老年代中進行分配擔保,將存活的對象移動老年代,這就是一次Minor GC的過程。
新生代
1. 示例代碼
- code
- VM參數說明
| -verbose:gc | 顯示GC的操作內容 |
| -Xms20M -Xmx20M | 設置堆大小為20M |
| -Xmn10M | 設置新生代的內存空間大小為10M |
| -XX:+PrintGCDetails | 打印GC中的變化 |
| -XX:SurvivorRatio=8 | 新生代中Eden區域與Survivor區域的大小比值 |
| -XX:+UseSerialGC | 在新生代和老年代中使用串行收集器,由于-verbose:gc參數對Parallel Scavenge收集器不起作用,無法顯示顯示GC的操作內容,因此采用串行收集器 |
- 示例代碼說明
- 該段代碼一共創建了4個數組對象,在給allocation4分配空間前的內存空間使用情況如下:
?
before MinorGC
- 需要執行一次MinorGC才能給allocation4分配空間,分配成功以后內存空間使用情況如下:
?
after MinorGC
2. GC日志
?
Minor GC日志
-
[GC [DefNew ... ...]
-
GC日志開頭的信息通過設置-verbose:gc參數后才能輸出。
-
"[GC"和"[Full GC"說明這次垃圾收集的停頓類型,如果這次GC發生了Stop-The-World,則為"[Full GC",否則為"[GC"
-
"[DefNew "表示GC發生的區域為Serial收集器的新生代中,DefNew是"Default New Generation"的縮寫。Serial收集器的老年代和永久代分別表示為"Tenured"、"Perm"
-
** eden space 8192K, 52% used**
-
新生代的Eden區總共大小為8MB,使用掉的4MB是用來存放allocation4對象
-
tenured generation total 10240K, used 6144K
-
老年代大小為10MB,使用掉的6MB是用來存放allocation1、allocation2和allocation3這3個對象
2.2 大對象直接進入老年代
1. 示例代碼
- code
- VM參數說明
| -XX:PretenureSizeThreshold=3145728 | 所占用內存大于該值的對象直接分配到老年代,3145728為3MB |
- 示例代碼說明
該段代碼創建了一個數組對象allocation,大小為4MB,已經超出PretenureSizeThreshold設置的范圍,該對象將直接被分配到老年代中。
2. GC日志
大對象直接進入老年代-GC日志
- tenured generation total 10240K, used 4096K
老年代大小為10MB,用掉的4MB用來存放allocation對象
2.3 長期存活的對象進入老年代
1. 示例代碼
- code
- VM參數說明
| -XX:MaxTenuringThreshold=1 | 對象晉升為老年代的年齡閥值為1 |
- 示例代碼說明
該段代碼創建了3個數組對象,當執行到"allocation3 = new byte[4 * _1MB]; "時,Eden已經被占用了256KB + 4MB,而創建allocation3需要4MB,已經超過Eden的大小8MB,需要先發生一次MinorGC,才能保證有空間存放allocation3
2. GC日志
-
設置參數為MaxTenuringThreshold=1的運行結果
-
由GC日志開頭的兩句"[GC [DefNew"可知,該段代碼一共發生了2次GC,第一次是"allocation3 = new byte[4 * _1MB]; ",第二次是執行allocation3 = null時
-
allocation1在經過第一次GC時,對象年齡變成了1,由于設置的MaxTenuringThreshold=1,當發生第二次GC時,allocation1的年齡已經超出了設置的閥值,allocation1進入到老年代,因此,新生代的from space使用空間為0,對應GC語句為from space 1024K, 0% used
?
MaxTenuringThreshold=1
- 設置參數為MaxTenuringThreshold=15的運行結果
由于設置的MaxTenuringThreshold=15,發生第二次GC時,allocation1的年齡沒有超出設置的閥值,因此,新生代的from space使用空間不為0,對應GC語句為from space 1024K, 44% used
?
MaxTenuringThreshold=15
3. 參考
- 深入理解Java虛擬機:JVM高級特性與最佳實踐(第2版)
總結
以上是生活随笔為你收集整理的JVM:GC日志解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 04.Java 堆内存 新生代 老年代?
- 下一篇: Java:异常处理的一些注意事项