垃圾回收機制
自動垃圾收集
自動垃圾收集是查看堆內存,識別正在使用哪些對象以及哪些對象未被刪除以及未使用對象的過程。
使用中的對象或引用的對象意味着程序的某些部分仍然維護指向該對象的指針。
程序的任何部分都不再引用未使用的對象或未引用的對象,因此可以回收未引用對象使用的內存。
像C這樣的編程語言中,分配和釋放內存是一個手動過程。
在java中,解除分配內存的過程由垃圾收集器自動處理。
如何確定內存需要被回收
該過程的第一步稱爲標記。這是垃圾收集器識別哪些內存正在使用而哪些不在使用的地方。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-88hj1qm6-1589444985942)(images/標記.png)]
不同類型內存的判斷方式:
- 對象回收 - 引用計數(解決不了循環引用的問題)
- 對象回收 - 可達性分析(重點研究)
- 方法區回收(類的卸載)
可達性分析算法
順藤摸瓜…找到一個入口…
引用類型和可達性級別
引用類型:
- 強引用(StrongReference):最常見的普通對象引用,只要還有強引用指向一個對象,就不會回收。obj = new 。。。
- 軟引用(SoftReference):JVM認爲內存不足時,纔會去試圖回收軟引用指向的對象。(緩存場景)
- 弱引用(WeakReference):雖然是引用,但隨時可能被回收掉。
- 虛引用(PhantomReference):不能通過他訪問對象。提供了對象被finalize以後,指向指定邏輯的機制(Cleaner堆外內存)
可達性級別:
- 強可達(Strongly Reachable):一個對象可以有一個或多個線程可以不通過各種引用訪問到的情況。- 強引用
- 軟可達(Softly Reachable):就是當我們只能通過軟引用才能訪問到對象的狀態。- 軟引用
- 弱可達(Weakly Reachable):只能通過弱引用被清除的時候,就符合銷燬條件。- 弱引用
- 幻象可達(Phantom Reachable):不存在其他引用,並且finalize過了,只有幻象引用指向這個對象。- 虛引用
- 不可達(unreachable):意味着對象可以被清除了。
垃圾收集算法
標記-清除(Mark-Sweep)算法:首先標識出所有要回收的對象,然後進行清除。
標記、清除過程效率有限,有內存碎片化問題,不適合特別大的堆;收集算法基本基於標記-清除的思路進行改進。
**複製(Copying)算法:**劃分兩塊同等大小的區域,收集時將活着的對象複製到另一塊區域。
拷貝過程中將對象順序放置,就可以避免內存碎片化。複製+預留內存,有一定的浪費。
**標記-整理:**類似於標記-清除,但爲避免內存碎片化,它會在清理過程中將對象移動,以確保移動後的對象佔用連續的內存空間。
分帶收集
根據對象的存活週期,將內存劃分爲幾個區域,不同區域採用合適的垃圾收集法。
新對象會分配到Eden,如果超過-XX:+PretenureSizeThreshold:設置大對象直接進入老年代的閾值。
新生代回收算法:複製算法
老年代標記整理算法:
minorGC:指新生代的GC
majorGC:指老年代的GC
fullGC:整個堆的GC
垃圾收集器
串行收集器-Serial GC -XX:UseSerialGC
新生代和老年代採用不同的參數進行配置
不適合多核處理器…
並行收集器-Parallel GC --XX:+UseParallelGC
新生代和老年代採用不同的參數進行配置
特點:將單線程變成了多線程
問題:串行收集器和並行收集器都會有一個stop-the-world,停止所有動作進行垃圾收集,有停頓時間。
併發收集器-CMS(Concurrent Mark Sweep) GC -XX:+UseConcMarkSweepGC
專用老年代,基於標記-清除(Mark-Sweep)算法,設計目標是儘量減少停頓時間。
採用的標記-清除算法,存在着內存碎片化問題,長時間運行等情況下發生full GC,導致惡劣的停頓。
CMS會佔用更多的CPU資源,並和用戶線程爭搶。
減少了停頓時間,這一點對於互聯網web等對時間敏感的系統非常重要,一直到今天,任然有很多系統使用CMSGC。
初始標記目的:找到GCroot
並行收集器-PraNew GC -XX:+UseParNewGC
新生代GC實現,它實際是Serial GC的多線程版本。
可以控制線程數量,參數: -XX:ParallelGCThreads
最常見的應用場景是配合老年代的CMS GC工作。參數: -XX:UseConcMarkSweepGC
在jdk中1.8中放棄維護了CMS GC