天天看點

回顧GC是如何判斷哪個對象應該被回收問題

一 概述

Java程式中,當一個對象沒有被其它對象引用時,則該對象對于虛拟機而言就應該被回收的對象,其占用的記憶體空間需要被釋放,同時對象也會被銷毀。

二 判斷對象應該被回收的具體算法

1. 引用計數算法

該算法通過判斷對象的引用數量來決定對象是否可以被回收,在此機制下,堆中每個對象都存在一個引用計數器,當一個對象建立後被配置設定一個引用之後則對應的引用計數器加1,當引用完成後則引用計數器相應的減1,當某個對象的引用計數器為0的時候後,則會被虛拟機作為垃圾進行回收,并釋放其所占用的記憶體空間。

優點:引用計數算法的執行效率高,程式執行所受的影響較小。

缺點:引用計數算法無法檢測出循環引用(父對象引用子對象,子對象引用父對象),其記憶體空間無法被回收,進而導緻記憶體洩漏。

2. 可達性分析算法

該算法通過判斷對象的引用鍊是否可達來決定對象是否會被作為垃圾進行回收。

該算法是從離散數學的圖論中引入,将程式的所有引用作為一張圖,通過将一些GC Roots對象作為起始點,從這些結點開始向下搜尋,搜尋所做過的路徑被稱為引用鍊,如果某個GC Roots沒有與任何引用鍊相連,則稱GC Roots到該對象為不可達,此時該對象可以作為垃圾進行回收,然後釋放其所占據的記憶體空間。

三 GC Roots執行個體

  • 在虛拟機棧(棧幀中的本地變量表)中引用的對象,譬如各個線程被調用的方法堆棧中使用到的參數,局部變量,臨時變量等。
  • 在方法區中類靜态屬性引用的對象,如Java類的引用類型靜态變量。
  • 在方法區中常量引用的對象,譬如字元串常量池(String Table)裡的引用。
  • 在本地方法棧中JNI(即通常所說的Native方法)引用的對象,。
  • 所有别同步鎖(synchronized關鍵字)所持有的對象。
  • Java虛拟機内部的引用,如基本資料類型對應的Class對象,一些常駐的異常對象(比如NullPointException,OutOfMemoryError)等,還有系統類加載器。