JVM 系列文章之 物件存活分析 - 引用計數 and 可達性分析
前言
在垃圾回收器回收物件時,我們如何判斷哪些物件是"活"的,哪些是"死"的,關於判斷物件存活的方法主要分為兩類: 引用計數法 和 可達性分析演算法
引用計數法
引用計數器就是: 給物件中新增一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減一;任何時刻計數器為 0 的物件就是不可能再被使用的,可以此時進行回收。
但是引用計數法有一個很大的缺陷,就是它很難解決物件之間相互迴圈引用的問題。
可達性分析演算法
在主流的商用程式語言(Java,C#等)的主流實現中,都是稱透過可達性分析來判斷物件是否存活的。
R大在知乎上有關可達性分析演算法的回答是:
Tracing GC 的根本思路就是: 給定一個集合的引用作為根出發,透過引用關係遍歷物件圖,能被遍歷到的(可達到的)物件就被判定為存活,其餘物件 (也就是沒有被比遍歷到的)就自然被判定為死亡,注意的是: tracing GC的本質是透過找出所有活物件來把其餘空間認定為"無用",而不是找出所有死掉的物件並回收它們佔用的空間
這裡的集合的引用就是 "GC Roots",所謂 "GC Roots",或者說tracing GC的"根集合",就是一組必須活躍的引用。下圖關於可達性分析演算法的圖示:
gcroots
物件obj4,obj5,obj6雖然相互有關聯,但是它們到 GC Roots是不可達的,所以它們將會判定為可回收的物件
要實現語義正確的tracing GC,就必須要能完整列舉出 所有的GC Roots,否則就可能會漏掃描應該存活的物件,導致GC錯誤回收了這些被漏掃的活物件。
哪些引用是 GC Roots
GC roots對應的引用可能包括:
所有Java執行緒當前活躍的棧幀裡指向 GC堆裡的物件的引用;換句話說,當前所有正在被呼叫的方法的引用型別的引數/區域性變數/臨時值
VM的一些靜態資料結構裡指向 GC堆裡的物件的引用,例如說 Hotspot VM裡的Universe裡有很多這樣的引用
(看情況)所有當前被載入的Java類
(看情況)Java類的引用型別靜態變數
(看情況)Java類的執行時常量池裡的引用型別常量(String或Class型別)
(看情況)String常量池(StringTable)裡的引用
注意,是一組必須活躍的引用,不是物件。
Java可達性分析演算法會不會出現迴圈引用問題?
從前面那張圖中我們就可以看出 GC Roots是單獨出來的,在物件圖之外,以下摘自 R大的回答:
GC Root在物件圖之外,是特別定義的"起點",不可能被物件圖內的物件所引用。
一個常見的誤解就是 以為GC Root是一組物件,實際上GC Root通常是一組特別管理的指標,這些指標是 tracing GC 的trace 的起點,它們不是物件圖裡物件,物件也不可能引用到這些"外部"的指標,另外,tracing GC能夠正確處理迴圈引用。保證每個活物件只會被訪問一次就能確定其存活性,物件圖裡是否存在迴圈引用,tracing GC都能判斷物件的存活與否。
這裡談到GC Roots是指標,之前說的是引用,本質它們的意思是一樣的,指標也就是引用。在官方的解釋是:
garbage collection root A pointer into the Java object heap from outside the heap. These come up, e.g., from static fields of classes, local references in activation frames, etc.
官方的意思是由heap外部指向 heap內的物件的指標,指標另一種說法也是引用。
小結
上面的分析更多的是參考了 R大在知乎上對相應問題的解答,R大是國內JVM巨牛級人物,他的回答都是非常權威的,所以學習 JVM的知識可以多參考 R大的分析。目前本人對 JVM也是一枚渣渣級選手,現在輸出對JVM的一些學習筆記。如有錯誤之處,歡迎指出。
作者:pjmike
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2310/viewspace-2818103/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入分析JVM中的物件及引用(十六)JVM物件
- Netty原始碼分析之ByteBuf引用計數Netty原始碼
- Netty系列文章之服務端啟動分析Netty服務端
- JVM 系列文章之 Full GC 和 Minor GCJVMGC
- Python中的物件引用、可變性和垃圾回收Python物件
- 物件的引用計數與dealloc物件
- JVM 系列文章之 GC 演算法淺析JVMGC演算法
- Volatile可見性分析(一)
- JVM系列(三) - JVM物件探祕JVM物件
- JVM 系列文章之 Java 的記憶體區域JVMJava記憶體
- Python學習之變數、物件和引用Python變數物件
- Java虛擬機器02——物件存活判斷和4種引用Java虛擬機物件
- JVM原始碼分析之Metaspace解密JVM原始碼解密
- Dubbo原始碼分析之服務引用原始碼
- JVM快速調優手冊v1.0之六:JVM引數設定、分析JVM
- drf快速使用 CBV原始碼分析 drf之APIView分析 drf之Request物件分析原始碼APIView物件
- Python學習之路27-物件引用、可變性和垃圾回收Python物件
- 瞭解Java物件,簡單聊聊JVM調優分析Java物件JVM
- js系列文章之 : 判斷 object 物件是否為空JSObject物件
- 通過String的不變性案例分析Java變數的可變性Java變數
- vue原始碼分析系列之入口檔案分析Vue原始碼
- 併發程式設計系列之Lock鎖可重入性與公平性程式設計
- JVM之垃圾回收機制詳解分析JVM
- PHP物件導向之&引用PHP物件
- JVM - 引用JVM
- 004-JVM-Java中使用的標記階段的演算法:可達性分析演算法中GC Roots有哪些JVMJava演算法GC
- iOS引用計數管理之揭祕計數儲存iOS
- JVM dump和分析JVM
- JVM分析工具概述JVM
- JVM的逃逸分析JVM
- JVM當機分析JVM
- Sentinel系列之SlotChain、NodeSelectorSlot、ClusterBuilderSlot分析AIUI
- 《JavaScript物件導向精要》系列文章JavaScript物件
- 效能測試之JVM的故障分析工具VisualVMJVMLVM
- JVM之調優及常見場景分析JVM
- 物件導向分析與設計(OOAD)物件
- 網路安全可程式設計性的資料日誌管理分析程式設計
- iOS 開發刷題系列三:NSString 引用計數iOS