《深入理解Java虛擬機》讀後總結
JVM的GC概述
GC即垃圾回收,是指jvm用於釋放那些不再使用的對象所佔用的內存。
在充分理解了垃圾收集算法和執行過程後,纔能有效的優化它的性能。
有些垃圾收集專用於特殊的應用程序。比如,實時應用程序主要是爲了避免垃圾收集中斷,而大多數OLTP應用程序則注重整體效率。
垃圾收集的目的在於清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。兩種常用的方法是引用計數和對象引用遍歷。
引用計數
引用計數存儲對特定對象的所有引用數,也就是說,當應用程序創建引用以及引用超出範圍時,jvm必須適當增減引用數。當某對象的引用數爲0時,便可以進行垃圾收集。
對象引用遍歷
早期的jvm使用引用計數,現在大多數jvm採用對象引用遍歷。對象引用遍歷從一組對象開始,沿着整個對象圖上的每條鏈接,遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,則將它作爲垃圾收集。在對象遍歷階段,gc必須記住哪些對象可以到達,以便刪除不可到達的對象,這稱爲標記(marking)對象。
基本的回收算法:
空間維度:標記-清除、標記-壓縮、標記-複製、增量回收、分代回收
時間維度:串行回收、併發回收、並行回收
標記-清除:
標記清除的算法最簡單,主要是標記出來需要回收的對象,然後然後把這些對象在內存的信息清除,會產生大量內存碎片。
標記-壓縮
有時也叫標記-清除-壓縮收集器,這個算法是在標記-清除的算法之上進行剪切操作,將存活對象壓縮在一起,減少內存碎片。由於壓縮空間需要一定的時間,會影響垃圾收集的時間。
標記-複製
這個算法是把內存分配爲兩個空間,一個空間(A)用來負責裝載正常的對象信息,另外一個內存空間(B)是垃圾回收用的。
每次把空間A中存活的對象全部複製到空間B裏面,在一次性的把空間A刪除。
這個算法在效率上比標記-清除-壓縮高,但是需要兩塊空間,對內存要求比較大,內存的利用率比較低。適用於短生存期的對象,持續複製長生存期的對象則導致效率降低。
增量回收:
增量回收器:把堆分爲多個域,每次對從一個域進行垃圾回收。這樣只會早點一小部分程序暫停。
分代回收:
基於對對象生命週期分析後得出的垃圾回收算法。把對象分爲年青代、年老代、持久代,對不同生命週期的對象使用不同的算法進行回收。
串行回收:
用單線程處理所有垃圾回收工作,因爲無需多線程交互,所以效率比較高。但是,也無法使用多處理器的優勢,所以此收集器適合單處理器機器
並行回收:
用多線程處理所有垃圾回收工作,利用多核處理器的優勢。對於空間不大的區域(如young generation),採用並行收集器停頓時間很短,回收效率高,適合高頻率執行。但是如果線程數量過多,導致線程之間頻繁調度,也會影響性能。一半並行收集的線程是處理器的個數。
併發回收:
併發收集器GC時GC線程和應用線程大部分時間是併發執行,只是在初始標記(initial mark)和二次標記(remark)時需要stop-the-world,這可以大大縮短停頓時間(pause time),所以適用於響應時間優先的應用,減少用戶等待時間。由於GC是和應用線程併發執行,只有在多CPU場景下才能發揮其價值,在一個N個處理器的系統上,併發收集部分使用K/N個可用處理器進行回收,一般情況下1<=K<=N/4。在執行過程中還會產生新的垃圾floating garbage(浮動垃圾),如果等空間滿了再開始GC,那這些新產生的垃圾就沒地方放了(併發收集器一般需要20%的預留空間用於這些浮動垃圾),這時就會啓動一次串行GC,等待時間將會很長,所以要在空間還未滿時就要啓動GC。mark和sweep操作會引起很多碎片,所以間隔一段時間需要整理整個空間,否則遇到大對象,沒有連續空間也會啓動一次串行GC。採用此收集器,收集頻率不能大,否則會影響到cpu的利用率,進而影響吞吐量。
JVM的GC觸發原理
JVM的GC主要是對堆內存的回收,
一般把新生代的GC稱爲minor GC ,把老年代的GC成爲 full GC,所謂full gc會先出發一次minor gc,然後在進行老年代的GC。
首先想eden區申請分配空間,如果空間夠,就直接進行分配,否則進行一次Minor GC。
minor GC 首先會對Eden區的對象進行標記,標記出來存活的對象。然後把存活的對象copy到From空間。
如果From空間足夠,則回收eden區可回收的對象。
如果from內存空間不夠,則把From空間存活的對象複製到To區,
如果TO區的內存空間也不夠的話,則把To區存活的對象複製到老年代。
如果老年代空間也不夠(或者達到觸發老年年垃圾回收條件的話)則觸發一次full GC。
簡單方向就是Eden->From->To->Old,如下圖所示:
默認是不會對持久帶(方法區)進行垃圾回收的,設置參數可回收:-XX:+CMSClassUnloadingEnabled
JVM支持的GC收集器
JVM採用的是分代回收,不同代有不同的垃圾收集器
如圖所示:連線的是可以組合使用
各個收集器的細節我就不在這裏COPY/PASTE了,SerialOld收集器在書的圖中沒有,是我後加上的,其實很少使用。
感興趣的可以試讀,試讀地址http://book.51cto.com/art/201107/278857.htm,有前三章的內容。