淺談GC垃圾回收機制

這裏只是淺談一下我自己對GC的理解,如果有什麼不對的地方歡迎大家指正交流

GC的定義

GC就是常說的jvm的垃圾回收機制,粗略的理解就是jvm虛擬機可根據複雜的算法策略判斷程序中的一段資源是否爲可回收狀態,而進行自動回收,釋放內存資源的一個過程。

以前JVM判斷對象存活還是死亡是使用引用計數算法,但現在是使用類似於樹形結構的可達性分析算法,也就是GC roots算法。引用計數算法我知道的好像是redis還在用其進行內存回收。

垃圾回收是發生在內存堆區中的,在這裏我就不畫了,先來個網上找的jvm的體系結構圖

JVM體系結構圖

圖片出處:https://www.cnblogs.com/hexinwei1/p/9406239.html

上方的運行時數據區就是常說的jvm運行內存

 

GC Roots算法

我的理解就是按樹狀結構以稱爲GC Roots的一些對象作爲起始節點, 開始向下搜索, 搜索過程中所走過的節點引用路徑就是引用鏈,一個堆中一個對象到 GC Roots 沒有任何引用鏈可以連接時(就是沒有任何指針可以指向當前對象內存地址),則證明此對象當前狀態是不可用的,也就是這個對象死了。

 

回收策略

有四種算法 (標記、複製、標記整理、分代收集),分代收集是對前三種的整合,當前jvm虛擬機回收策略是使用分代收集算法。

 

標記算法就是將內存中GC root判斷爲死亡作爲的對象作爲未標記資源直接清除

標記算法的不足就是效率低,對整個內存堆區的標記和清除都是依次進行的,所以效率都不高。並且還有空間問題,這種方法清除資源時會產生大量不連續的內存碎片,內存中不連續的空間碎片太多可能會導致在程序運行過程中分配較大對象時,無法找到足夠的連續內存,使得程序要提前發出另一次垃圾收集指令。

 

複製算法就是將內存空間分成大小相同的兩塊,每次只使用一塊,一個內存塊滿了,執行垃圾回收時將存活對象複製到空白的那一塊,然後清除正在使用的內存塊,清除後將存活對象再放回來。

複製算法的不足是不適用於存活對象較多的情景,存活對象較多時效率較低,因爲正在使用的內存一直是原來的一半了。

 

標記整理算法是對標記算法的優化,就是在將要清理垃圾資源時,將存活對象壓縮到內存的一角,然後將這一角外的所有內存空間直接清理

 

三種算法比較

時間複雜度:複製>標記整理>標記

內存利用率:標記整理 > 標記清除 > 複製

內存整齊度:複製 = 標記整理 > 標記清除

老年代存放的對象存活的時間較長,而且垃圾回收的頻率不如新生代的頻繁 ,所以標記-整理算法和標記算法常用於老年代的回收

 

分代收集就是根據對象生存週期的不同將內存劃分幾塊,一般是將堆區分爲新生代和老年代,然後根據這兩個年代的不同特點分別使用上面的算法。

新生代對象大多生命週期較短,所以每次垃圾回收時都有大批對象死去,只有少量存活,這樣就比較適合用複製算法,只需要付出少量的存活對象的複製成本就可以完成垃圾回收。

老年代對象大多生命週期較長,對象存活率高、而且沒有額外內存空間對它進行分配擔保,所以就需要使用標記算法或標記整理算法來進行垃圾回收。

 

當然像老年代和新生代的對象區分規則和內存分配擔保機制等這次就先不說了,這次就寫到這,歡迎交流
 

發佈了6 篇原創文章 · 獲贊 1 · 訪問量 795
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章