JVM 如何確定死亡物件?
引用計數演算法(Reference Counting) 屬於垃圾收集器的早期實現演算法了,它指的是在建立物件時關聯一個與之相對應的計數器,當此物件被使用時加 1,相反銷燬時 -1。當此計數器為 0 時,則表示此物件未使用,可以被垃圾收集器回收。
引用計數演算法的優缺點很明顯,其優點是垃圾回收比較及時,實時性比較高,只要物件計數器為 0,則可以直接進行回收操作;而缺點是無法解決迴圈引用的問題,比如以下程式碼:
public class RefCounterTest { // 物件 A static class RefObjectA { private RefObjectB refObjectB; public void setRefObjectB(RefObjectB refObjectB) { this.refObjectB = refObjectB; } } // 物件 B static class RefObjectB { private RefObjectA refObjectA; public void setRefObjectA(RefObjectA refObjectA) { this.refObjectA = refObjectA; } } // 測試程式碼 public static void main(String[] args) { RefObjectA objectA = new RefObjectA(); RefObjectB objectB = new RefObjectB(); objectA.setRefObjectB(objectB); objectB.setRefObjectA(objectA); objectA = null; objectB = null; } }
如以上程式碼所示,即使是將 main 方法中的 objectA 和 objectB 都設定為 null,也就是這兩個物件都徹底不使用了,但是因為二者存在相互引用的關係,所以它們所對應的物件計數器不為 0,這樣迴圈引用導致垃圾資料無法被清除的事件就產生了。
可達性分析演算法(Reachability Analysis) 是目前主流虛擬機器中,使用最廣泛的判斷垃圾物件的實現演算法,它指的是從物件的起點(GC Roots)開始向下搜尋,如果物件到 GC Roots 沒有任何引用鏈相連時,也就是說此物件到 GC Roots 不可達時,則表示此物件可以被垃圾回收器所回收,如下圖所示:
在 Java 語言中,可作為根節點(GC Roots)的物件有以下 4 類:
1. Java 虛擬機器棧中的引用物件,也就是 Java 虛擬機器棧幀中,本地變數表所儲存的(引用)物件。在 Java 虛擬機器棧幀中儲存的物件都是將來執行時,要使用的物件,所以和引用物件相關的物件都不能被回收;
2. 本地方法棧中的引用物件和 Java 虛擬機器棧中的引用物件類似,也不能被回收;
3. 方法區中類靜態屬性引用的物件也可以作為 GC Roots;
4. 方法區中常量引用的物件也可以作為 GC Roots。因為常量是儲存在常量池中的,屬於全域性可使用的物件,所以也能作為 GC Roots。
不管是引用計數法還是可達性分析演算法都與物件的“引用”有關,這說明物件的引用決定了物件的生死,而 Java 中的引用也比較複雜,它從 JDK 1.2 之後,(引用)分成了以下 4 種型別:
1. 強引用:在程式碼中普遍存在的,類似 Object obj = new Object() 這類引用,只要強引用還在,垃圾收集器永遠不會回收掉被引用的物件;
2. 軟引用:是一種相對強引用弱化一些的引用,可以讓物件豁免一些垃圾收集,只有當 JVM 認為記憶體不足時,才會去試圖回收軟引用指向的物件,JVM 會確保在丟擲 OutOfMemoryError 之前,清理軟引用指向的物件;
3. 弱引用:非必需物件,但它的強度比軟引用更弱,被弱引用關聯的物件只能生存到下一次垃圾收集發生之前;
4. 虛引用:也稱為幽靈引用或幻影引用,是最弱的一種引用關係,無法透過虛引用來獲取一個物件例項,為物件設定虛引用的目的只有一個,就是當著個物件被收集器回收時收到一條系統通知。
垃圾物件的判定有兩種常用的演算法:引用計數器演算法和可達性分析演算法。其中引用計數器演算法實現簡單、執行高效,但是存在迴圈引用的問題,所以主流的虛擬機器使用的都是可達性分析演算法,可達性分析演算法是從物件的根節點 GC Roots 向下搜尋,如果根節點相連就是正常的物件,否則為垃圾物件可以被垃圾回收器回收。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69901823/viewspace-2941739/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JVM是如何建立一個物件的?JVM物件
- JVM系列(三) - JVM物件探祕JVM物件
- 如何正確定義效能瓶頸
- Git如何確定當前所在分支Git
- 條款04: 確定物件被使用前已被初始化物件
- [JVM]物件建立過程JVM物件
- 深入理解JVM——物件JVM物件
- 3、JVM中的物件JVM物件
- JVM(八):Java 物件模型JVMJava物件模型
- 深入淺出JVM(十一)之如何判斷物件“已死”JVM物件
- 如何確定大資料分析的安全大資料
- 如何唯一確定一個 Java 類?Java
- JVM視角看物件建立JVM物件
- JVM-物件及物件記憶體佈局JVM物件記憶體
- 【Java面試】JVM如何判斷一個物件可以被回收Java面試JVM物件
- MySQL如何計算重要的指標,來確定配置是否正確MySql指標
- 「數倉面試」如何確定主題域?面試
- 身份認證之如何確定你就是“你”?
- [20190630]如何確定直方圖型別.txt直方圖型別
- [20210817]如何通過bbed確定undo段.txt
- 如何正確設定動態TextView的textSizeTextView
- JVM(四)-虛擬機器物件JVM虛擬機物件
- Java如何停止執行緒,確定你知道的都是正確的麼?Java執行緒
- 如何確定AI更值得信任?此處需@XAI……AI
- 淺談如何確定伺服器的數量伺服器
- 如何確定DevOps變更的優先順序?dev
- 如何確定敏捷是否適合你的團隊?敏捷
- 如何確定自己是否適合做程式設計師?程式設計師
- 翻頁後, 如何確定列表被重新整理?
- [20181031]如何確定db_link的程式號.txt
- JVM -- 物件的記憶體佈局JVM物件記憶體
- Java物件在JVM中長啥樣Java物件JVM
- 效能測試中如何確定TPS和併發數
- 如何確定Kaizen的實施機會?看完秒懂AI
- 企業該如何確定六西格瑪專案?
- 訓練神經網路時如何確定batch size?神經網路BAT
- 如何優雅的定義統一響應物件物件
- CAD中的物件顯示順序如何設定物件