1. 程式人生 > >垃圾回收機制算法分析

垃圾回收機制算法分析

虛擬 obj 碎片 地方法 區域 不可 大於 可能 enc

什麽是垃圾回收機制?
不定時的清理不可達對象,不可達對象不會立馬被回收,垃圾收集器在一個 Java 程序中是自動的,不能強制執行,即使我們已經清楚的確定這塊內存已經沒有用處了,應該被回收掉,也不能強制執行,我們能做的只是調用 System.gc() 來建議垃圾回收器,這塊內存可以回收,但垃圾收集器回收不回收,什麽時候回收,都是不可知的
finalize() 方法的作用
在垃圾收集器回收對象前做必要的清理工作,這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的,該方法是在 Object 定義的,所以所有類都繼承了它,子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作
新生代和老生代

添加描述
Java 中的堆是 JVM 所管理的最大的一塊內存空間,在 Java 中,堆被分成了兩個內存空間,分別是新生代和老年代,新生代占 1/3,老生代占 2/3
新生代中存儲新創建的對象,垃圾收集器頻繁的活躍在新生代,新生代又分成三個部分,分別是 Eden、from 、to,默認比例是 8:1:1,當對象創建後,對象首先存放在 Eden 區域,經歷過一次垃圾回收後,如果對象還存活,就進入 from 區域或者 to 區域,新生代中的對象每經歷一個垃圾回收,對象年齡加1,達到一定年齡,進入老年代
老年代中存儲較為活躍的對象
如何判斷對象是否存活?
引用計數法
當一個對象被創建後,年齡默認為0,每經歷過一次垃圾回收,年齡就會增加1,如果年齡大於15就會存放到老年代中去,GC 線程不定期的回收,如果對象被引用,年齡加1,如果未被引用,年齡減1,如果年齡為0,會被垃圾回收機制認為是不可達對象,對其進行回收,引用計數法的缺點是很難解決循環引用的問題

根搜索算法
根搜索算法就是將名為 GC Roots 的對象作為起始點,往下進行搜索,搜索所經過的路徑稱為引用鏈(Reference Chain),當一個對象到 GC Roots 沒有任何引用鏈,則該對象是不可達的
如何獲取 GC Roots 對象?
虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中引用的對象
方法區中的類靜態屬性引用的對象
方法區中常量引用的對象
本地方法棧中 JNI 引用的對象
垃圾回收策略
標記清除算法
給每個對象根據是否可達做個標記,遍歷標記為不可達的對象,逐個刪除
應用場景:發生在老年代
優缺點:
優點

可以解決循環引用問題
必要時才回收
缺點

回收時,應用需要掛起
標記和清除的效率不高,尤其是要標記的對象很多的時候

會造成內存碎片
復制算法
如果 JVM 使用了coping 算法,當創建一個對象時,首先會存放到 Eden 區域,當掃描到對象比較活躍,就將這些活躍的對象存放在 from 區域或者 to 區域,註意,這兩個區域肯定有一個為空,如果對象存到了 form 區域,如果from 區域的對象隨著程序執行出現了不可達對象,會將可達對象復制到 to 區域,直接清空 from 區域
應用場景:發生在新生代
優缺點:
優點

解決碎片化問題、性能高
造成空間浪費,from 或 to 始終有一個是空的
標記壓縮算法
標記壓縮算法和標記清除算法類似,不同的是將對象按順序進行排列,直接將不可達對象一塊刪除
任意順序:即不考慮原先對象的排列順序,也不考慮對象之間的引用關系,隨意移動對象
線性順序:考慮對象的引用關系,例如 a 對象引用了 b 對象,則盡可能將 a 和 b 移動到一塊
滑動順序:按照對象原來在堆中的順序滑動到堆的一端
優缺點:
優點

解決內存碎片問題
缺點

在標記壓縮時,由於排序改變了對象位置,需要更新引用
分代算法
對於新生代,采用復制算法,對於老年代,采用標記->壓縮->清除算法
Minor GC 和 Full GC 區別:
Minor GC:即新生代 GC ,發生在新生代的垃圾收集動作,所以 Minor GC 十分頻繁,一般回收速度也較快,當 Eden 區域滿時,會觸發 Minor GC
Full GC:即老年代 GC,發生在老年代的垃圾收集動作,所以 Full GC 很少發生,速度也較 Minor GC 慢十倍,當老年代滿時,會觸發 Full GC,同時會清除新生代和老年代,當永久代滿時,也會觸發 Full GC,
JVM 的永久代中會發生垃圾回收嗎?
垃圾回收不會發生在永久代,如果永久代滿了或者是超過了臨界值,會觸發完全垃圾回收 Full GC

垃圾回收機制算法分析