1. 程式人生 > >Java GC工作機制 //TODO

Java GC工作機制 //TODO

感謝 千古壹號 公眾號的分享

以下為自己看了這篇文章後的整理記錄,方便記憶及複習。

GC的概念

GC:Garbage Collections 字面意思是垃圾回收器,釋放垃圾佔用的空間。讓建立的物件不需要像c、c++那樣需要程式設計師手動的delete、free掉 。對於c、c++的開發人員來說記憶體是開發人員分配的,也就是說還要對記憶體進行維護和釋放。對於Java程式設計師來說,一個物件的記憶體分配是在虛擬機器的自動記憶體分配機制的幫助下完成的,而對於在虛擬機器中不再需要的物件,Java也有一套專門回收記憶體的垃圾處理機制,這就是GC(垃圾收集器)

引用計數器演算法

引用計數器演算法是垃圾收集器中的早期策略。其核心思想是給物件中新增一個引用計數器,每當有一個地方引用它時,計數器值就加1;
當引用失效時,計數器值就減1;任何時刻計數器為0的物件就是不可能再被使用的。

在這種方法中,堆中每個物件例項都有一個引用計數。當一個物件被建立時,就將該物件例項分配給一個變數,該變數計數設定為1。當任何其它變數被賦值為這個物件的引用時,計數加1(a = b,則b引用的物件例項的計數器+1),但當一個物件例項的某個引用超過了生命週期或者被設定為一個新值時,物件例項的引用計數器減1。任何引用計數器為0的物件例項可以被當作垃圾收集。當一個物件例項被垃圾收集時,它引用的任何物件例項的引用計數器減1。

引用計數演算法的實現簡單,判定效率也高,大部分情況下是一個不錯的演算法。但是,主流的java虛擬機器並沒有選用引用計數演算法來管理記憶體,其中最主要的原因是:它很難解決物件之間相互迴圈引用的問題。

比如下面的程式碼就會造成迴圈引用,從而不能被GC回收:

Object objectA = new Object();
Object objectB = new Object();
objectA.field = objectB;
objectB.field = objectA;

根搜尋演算法

因為引用計數器演算法存在重大缺陷,所以JVM一般會採用一種新的演算法,叫做根搜尋演算法。

它的處理方式就是,設立若干種根物件(GC roots),當任何一個根物件到某一個物件均不可達(即不再GC roots的引用鏈內)時,則認為這個物件是可以被回收的。

在java中,以下物件可以被稱作GC roots物件:

1、棧(棧幀中的本地變量表)中引用的物件。
2、方法區中的靜態成員。
3、方法區中的常量引用的物件(全域性變數)
4、本地方法棧中JNI(一般說的Native方法)引用的物件。

其中:第一和第四種都是指的方法的本地變量表,第三種主要指的是宣告為final的常量值。

在根搜尋演算法的基礎上,又拓展了三種演算法,他們分別是標記-清除複製標記-整理

標記-清除
複製
標記-整理

分代收集演算法(存活時間短的新生代,和存活時間長的老生代)