GC 是什么
GC 是垃圾收集的意思(GabageCollection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java 提供的 GC 功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java 語言沒有提供釋放已分配內存的顯示操作方法
Java 垃圾回收機制
在 Java 中,程序員是不需要顯示地去釋放一個對象的內存的,而是由虛擬機自行執行。在 JVM 中,有一個垃圾回收線程,它是低優先級的,在正常情況下是不會執行的,只有在虛擬機空閑或者當前堆內存不足時,才會觸發執行,掃面那些沒有被任何引用的對象,并將它們添加到要回收的集合中,進行回收。
如何判斷一個對象是否存活?(或者 GC 對象的判定方法)
判斷一個對象是否存活有兩種方法:
1. 引用計數法
所謂引用計數法就是給每一個對象設置一個引用計數器,每當有一個地方引用這個對象時,就將計數器加一,引用失效時,計數器就減一。當一個對象的引用計數器為零時,說明此對象沒有被引用,也就是“死對象”,將會被垃圾回收.
引用計數法有一個缺陷就是無法解決循環引用問題,也就是說當對象 A 引用對象 B,對象 B 又引用者對象 A,那么此時 A、B 對象的引用計數器都不為零,也就造成無法完成垃圾回收,所以主流的虛擬機都沒有采用這種算法。
2. 可達性算法(引用鏈法)
該算法的思想是:從一個被稱為 GC Roots 的對象開始向下搜索,如果一個對象到 GC Roots 沒有任何引用鏈相連時,則說明此對象不可用。
在 Java 中可以作為 GC Roots 的對象有以下幾種:
? 虛擬機棧中引用的對象
? 方法區類靜態屬性引用的對象
? 方法區常量池引用的對象
? 本地方法棧JNI引用的對象
雖然這些算法可以判定一個對象是否能被回收,但是當滿足上述條件時,一個對象比不一定會被回收。當一個對象不可達 GC Root 時,這個對象并不會立馬被回收,而是處于一個死緩的階段,若要被真正的回收需要經歷兩次標記.
如果對象在可達性分析中沒有與 GC Root 的引用鏈,那么此時就會被第一次標記并且進行一次篩選,篩選的條件是是否有必要執行 finalize() 方法。當對象沒有覆蓋 finalize() 方法或者已被虛擬機調用過,那么就認為是沒必要的。 如果該對象有必要執行 finalize() 方法,那么這個對象將會放在一個稱為 F-Queue 的對隊列中,虛擬機會觸發一個 Finalize() 線程去執行,此線程是低優先級的,并且虛擬機不會承諾一直等待它運行完,這是因為如果 finalize() 執行緩慢或者發生了死鎖,那么就會造成 F-Queue 隊列一直等待,造成了內存回收系統的崩潰。GC 對處于 F-Queue 中的對象進行第二次被標記,這時,該對象將被移除” 即將回收” 集合,等待回收。