性能測試三十五:jvm垃圾回收-GC
垃圾回收-GC
三個問題
哪些內存需要回收?
什麽時候回收?
如何回收?
YoungGC和FullGC:
新生代引發的GC叫YoungGC
老年代引發的GC叫FullGC
FullGC會引起整個Jvm的用戶線程暫停,待垃圾回收完畢後,才繼續運行
引用的定義:
如果reference類型的數據中存儲的數值代表的是另外一塊內存的起始地址,就稱這塊內存代表一個引用
對象存活狀態:
確定對象“存活”還是“死去”:以下兩種算法原理都一樣,就是看當前這個對象,是否有引用正在指向它,如果有,就是還有用的,如果沒有,就清除
第一種:引用計數算法(已被廢棄):
如果當前對象有一個引用正在指向它,則在其對應的計數器上+1,統計完後計數器上為0的就代表沒用的對象,進行清除
第二種:根搜索算法(GC Roots):
先找到對象,再根據對象去搜索,看有沒有引用正指向它,如果有,就是還有用的,如果沒有,就清除
永久代的垃圾回收:
永久代回收“性價比”比較低,因為裏面放的都是靜態的對象,都是有用的,無法回收,就算觸發了一次回收,占用內存還是不會變
主要回收
廢棄的常量
無用的類
類的所有實例都已經被回收
加載該類的ClassLoader已經被回收
該類的Class對象沒有在任何地方被引用
堆垃圾回收算法:
1、標記-清除算法
以兩種狀態個所有對象分類,然後清除掉可回收的部分
特點:
分為“標記”和“清除”兩個階段
標記完成後,統一回收
缺點:
效率,標記和清除過程效率都不高
空間,標記清除後會產生大量不連續的內存碎片
2、復制算法
把內存分為ab兩塊,觸發垃圾回收的時候,直接把a裏面可用的對象有序的復制到b裏面,並清空a(和新生代的原理一樣)
特點:
內存分為相等的兩塊
當一塊內存用完,將存活對象復制到另外一塊中,原內存一次性清理掉
復制時按照順序分配內存,無內存碎片問題
新生代使用此算法
缺點:
將內存分為兩半,利用率低
3、標記-壓縮算法
根據標記清除算法改良而來
特點:
先對存活對象進行標記
讓所有存活對象向一邊移動
清理掉存活對象邊界外的所有內存
註:老年代使用此算法
4、分代收集算法
當代的商業虛擬機都采用“分代收集”
根據對象的存活周期的不同將內存劃分成幾塊,一般Java堆分為新生代和老年代
新生代采用復制算法
老年代采用標記-壓縮算法
垃圾收集器
以上的所有算法,都只是理念,而垃圾收集器是內存回收算法的具體實現,沒有完美的收集器
Jvm不同的區域可以采用不同的垃圾收集器組合,主要有:
1、Serial收集器(串行)
單線程收集器
用戶線程全部停止(Stop the world)
Client模式下,新生代默認收集器
優點:簡單、高效
2、ParNew收集器(並行)
並行收集器,Serial收集器的多線程版本
Server模式下Jvm默認的新生代收集器
默認開啟的垃圾回收線程與cpu核數一致
3、CMS收集器(並發)
並發收集器(ConcurrentMarkSweep)
采用了標記-清除算法
並發收集、低停頓
缺點:
消耗cpu
會產生內存碎片
浮動垃圾(Concurrent Mode Failure
4、G1收集器
性能測試三十五:jvm垃圾回收-GC