Java JVM:垃圾回收問題

包括:

一. 垃圾回收基本概念

二. GC日誌


一. 垃圾回收基本概念

        垃圾回收也就是GC。那麼GC 在什麼時候,對什麼東西,做了什麼事情

1.1 在什麼時候

        首先需要知道,GC又分爲minor GC 和 Full Gc。Java 堆內存分爲新生代和老年代,新生代中又分爲1個Eden區域 和兩個 Survivor區域,當Eden區域內存不足的時候,就會觸發minor GC,當老年代內存不足的時候,就會觸發Full GC。但是,具體到什麼時刻執行,這個是由系統來進行決定,是無法預測的。


1.2 對什麼東西

        主要根據可達性分析算法,如果一個對象不可達,那麼就是可以回收的;如果一個對象可達,那麼這個對象就不可以回收。對於可達性分析算法,它是通過一系列稱爲“GC Roots” 的對象作爲起始點,當一個對象到 GC Roots 沒有任何引用鏈相接的時候,那麼這個對象就是不可達,就可以被回收。如下圖1:


圖1

       這個GC Root 對象可以是一些靜態的對象,Java方法的local變量或參數, native 方法引用的對象,活着的線程。


1.3 做了什麼事情

       主要做了清理對象,整理內存的工作。Java堆分爲新生代和老年代,採用了不同的回收方式。例如新生代採用了複製算法,老年代採用了標記整理法。在新生代中,分爲一個Eden 區域和兩個Survivor區域,真正使用的是一個Eden區域和一個Survivor區域,GC的時候,會把存活的對象放入到另外一個Survivor區域中,然後再把這個Eden區域和Survivor區域清除。那麼對於老年代,採用的是標記整理法,首先標記出存活的對象,然後再移動到一端。這樣也有利於減少內存碎片。


二. GC日誌

圖3


圖4


Full GC 信息與 Minor GC 的信息是相似的,這裏就不一個一個的畫出來了。
       從 Full GC 信息可知,新生代可用的內存大小約爲 18M,則新生代實際分配得到的內存空間約爲 20M(爲什麼是 20M? 請繼續看下面…)。老年代分得的內存大小約爲 42M,堆的可用內存的大小約爲 60M。可以計算出: 18432K ( 新生代可用空間 ) + 42112K ( 老年代空間 ) = 60544K ( 堆的可用空間 )
       新生代約佔堆大小的 1/3,老年代約佔堆大小的 2/3。也可以看出,GC 對新生代的回收比較樂觀,而對老年代以及方法區的回收並不明顯或者說不及新生代。並且在這裏 Full GC 耗時是 Minor GC 的 22.89 倍。
 


總結:

  1. 主要回收場所:JVM方法區,JVM方法棧。
  2. 回收方式: 新生代(複製算法),老年代(標記整理法)。
  3. 根據Young / Old 判斷是新生代還是老年代的 GC,然後就是給出 Young / Old ,整個堆內存 GC 前後的大小。 


參考:一個面試官對面試問題的分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章