JVM—引用計數和可達性分析算法(存活性判斷)


1 引用計數算法

1.1 算法思想

  給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;
  當引用失效時,計數器值就減1;
  任何時候計數器為0時的對象就是不能再被使用。

1.2 特點

  • 優點:實現簡單;判定效率高。
  • 缺點:很難解決對象之間相互循環引用的問題。(所以虛擬機不是通過引用計數算法判斷對象是否存活)

2 可達性分析算法

2.1 算法思想

  通過一系列稱為GC Roots 的對象作為起始點,從這些節點開始向下搜索,搜索走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連的時候,則證明此對象是不可用的。

2.2 GC Roots的對象

  • 虛擬機棧(棧幀中本地變量表)中引用的對象;
  • 方法區中類靜態屬性引用的對象;
  • 方法區中常量引用的對象;
  • 本地方法棧中JNI(Native方法)引用的對象;

3 對象存亡判斷

3.1 兩次標記過程

真正宣布一個對象已死,必須經歷兩次標記過程:

  1. 如果對象在進行可達性分析后發現沒有與GC Roots相連接的引用鏈,則將會被第一次標記並且進行一次篩選;
  2. 若這個對象被判定有必要執行finalize()方法,則該對象放置在一個叫F-Queue隊列中,並之后由VM自動建立的、低優先級的Finalizer線程去執行它。
  3. finalize()方法是對象逃脫死亡的最后一次機會,稍后GC將對F-Queue隊列中的對象進行第二次小規模的標記,若finalize()能夠救活自己,則第二次標記時,將被移除出“即將回收”的集合;若對象沒有完成自救,則回收。

3.2 補充

  1. 篩選的條件:這個對象有沒有必要去執行finalize()方法?當對象沒有覆蓋finalize()方法或者finalize()方法已經被VM掉用過,則“沒有必要執行“
  2. “執行”操作的觸發:是VM會觸發這個方法,而不承諾等它運行結束,原因:如果一個對象在finalize()方法中執行緩慢,或發生死循環,將導致F-Queue隊列中其他對象永遠處於等待,甚至導致整個內存回收系統崩潰。
  3. finalize()中對象自救:只要重新與引用鏈上的任何一個對象建立關聯即可,譬如把自己(this關鍵字)賦值給某個類變量或者對象的成員變量。finalize()最多只會被系統自動調用一次,所以自救機會只有一次。finalize()方法的運行代價搞,不確定大,無法保證各個對象的調用順序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM