今天開始實戰Java虛擬機之三:“虛擬機的工作模式”。
總計有5個系列
實戰Java虛擬機之三“G1的新生代GC”
實戰Java虛擬機之四“禁用System.gc()”
實戰Java虛擬機之五“開啓JIT編譯”
新生代GC的主要工作是回收eden區和survivor區。一旦eden區被佔滿,新生代GC就會啓動。新生代GC收集前後的堆數據如圖5.6所示,其中E表示eden區,S表示survivor區,O表示老年代。可以看到,新生代GC只處理eden和survivor區,回收後,所有的eden區都應該被清空,而survivor區會被收集一部分數據,但是應該至少仍然存在一個survivor區,類比其他的新生代收集器,這一點似乎並沒有太大變化。另一個重要的變化是老年代的區域增多,因爲部分survivor區或者eden區的對象可能會晉升到老年代。
圖5.6 G1的新生代GC
新生代GC發生後,如果打開了PrintGCDetails選項,就可以得到類似以下的GC日誌(這裏只給出了部分日誌,完全的日誌及其分析請看《實戰Java虛擬機》一書第5.4.6節):
1 2 3 4 5 6 7 | 0.336 : [GC pause (young), 0.0063051 secs] …. [Eden: 235 .0M( 235 .0M)-> 0 .0B( 229 .0M) Survivors: 5120 .0K-> 11 .0M Heap: 239 .2M( 400 .0M)-> 10 .5M( 400 .0M)] [Times: user= 0.06 sys= 0.00 , real= 0.01 secs] |
和其他回收器的日誌相比,G1的日誌內容非常豐富。當然我們最爲關心的依然是GC的停頓時間以及回收情況。從日誌中可以看到,eden區原本佔用235M空間,回收後被清空,survivor區從5M增長到了11M,這是因爲部分對象從eden區複製到survivor區,整個堆合計爲400M,從回收前的239M下降到10.5M。
節選自