JavaGC機制
主要完成三件事情:一、哪些內存需要回收。二、什麼時候回收。三、如何回收。
引用計數法
在對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就+1;當引用失效時,計數器的值就-1;任何時刻計數器的值爲零的對象就是不可能再被使用。
可達性分析算法
通過一系列的“GC Roots”的根對象作爲起始節點集,從這些節點開始,根據引用關係向下搜索,搜索過程中所走的路徑稱爲“引用鏈”,如果某個對象到GC Roots間沒有任何引用鏈相連,就證明GC Roots到該對象不可達,該對象就不可能再被使用。
finalize()方法
一個對象宣告死亡,需要經過兩次標記過程:第一次就是經過可達性算法分析沒有引用鏈與GC Roots相連,該對象就會被第一次標記。然後就會經過一次篩選,篩選的條件就是該對象是否被執行過finalize()方法。如果已經執行過或者沒有覆蓋,就不用執行。否則就會隊列裏執行該方法,該方法是對象逃脫死亡的最後一次機會。在隊列裏就會進行第二次標記。對象就會在finalize()方法裏面尋找重新與引用鏈上的任何一個對象建立關聯,只要建立關聯成功,就會被移除該隊列,就會避免被收集器收集。
四種回收算法
- 分代收集
弱分代:朝生夕滅
強分代:會熬過多次的垃圾收集
新生代,老年代之分 - 標記-清除算法
經歷“標記”和“清除”兩個階段。首先標記出所需要回收的對象,在標記完成後,統一回收掉所有被標記的對象。
缺點:會產生大量不連續的內存碎片。 - 標記-複製算法
將內存容量分成大小相等的兩塊,每次只使用其中的一塊。當使用的一塊內存使用完了,就將還活着的對象複製到另一塊,然後就把已使用的空間給清理掉。
缺點:如果對象存活多,效率低。
8:1:1 - 標記-整理算法
標記過程一樣,然後讓所有存活的對象都向內存的一端移動,然後清理掉邊界以外的內存。
移動缺點:暫停程序,分區影響吞吐量。
GC Roots對象
- 在虛擬機棧中引用的對象。比如:線程中被調用的方法堆棧中用到的參數、局部變量,臨時變量。
- 方法區中類靜態屬性引用的對象。比如:Java類的引用類型靜態變量。
- 方法區中常量的引用對象。比如:字符串常量池裏的引用。
- Java虛擬機內部引用。比如:基本數據類型的Class對象,系統類加載器。
- 被同步鎖持有的對象。