1. 程式人生 > >JVM如何判斷物件"死"和"活"

JVM如何判斷物件"死"和"活"

     堆中存放著幾乎所有的物件例項,垃圾收集器在堆堆進行回收前,首先要確定這些物件哪些還“活著”,哪些已經“死去”。方法有如下兩種:

(1)引用計數法

     演算法思想:為物件新增一個引用計數器,每當有一個地方引用該物件時,則該引用計數器值加1,;當引用失效時,則該引用計數器值減1;最後,計數器為0的物件就是不可能再被使用的,也即所謂的“死去”的物件。

    Java中並沒有使用這種演算法進行GC,最主要的原因是很難解決物件之間的相互迴圈引用的問題。如下程式碼:

public class TestReferenceCountingGC {
	
	public Object obj = null;
	
	public void testGc(){
		TestReferenceCountingGC obj1 = new TestReferenceCountingGC();
		TestReferenceCountingGC obj2 = new TestReferenceCountingGC();
		obj1.obj = obj2;
		obj2.obj = obj1;
		obj1 = null;
		obj2 = null;
		
		System.gc();
	}
}
    在上述程式碼中,obj1和obj2相互引用,除此之外,無其他任何引用,但因為相互引用對方導致引用計數器都不為0,因此無法通知GC收集器回收它們。

(2)根搜尋演算法

    Java中是使用根搜尋演算法(GC Roots Tracing)判斷物件是否存活的。

    演算法思想:選擇名為“GC Roots”的物件為起始點,從這些GC Roots節點開始向下搜尋,搜尋走過的路徑稱之為引用鏈(Reference Chain),當一個物件到GC Roots沒有任何引用鏈時(即不可達,兩者之間無通路),則認為該物件為不可用的。如下圖:

                               

    如上圖,Object3和Object4是相互連線的,但和GC Roots無通路,因此Object3和Object4被認為是可回收的物件。

   在Java中,可作為GC Roots的物件有如下:

    a、虛擬機器棧(棧幀中的本地變量表)中的引用的物件

    b、方法區中的常量引用的物件

    c、方法區中的類靜態屬性引用的物件

    d、本地方法棧中JNI(Native方法)的引用的物件。

(3)引用的分類

    a、強引用(Strong Reference)

          程式程式碼中普遍存在的,比如Object obj = new Object(),只要存在強引用,GC收集器永遠不會回收被引用的物件。

    b、軟引用(Soft Reference)

          非必須的物件,是否回收,要看當前記憶體情況,如果緊張,則進行回收,否則不回收。當程式丟擲記憶體溢位異常時,肯定不存在這種型別的物件。

    c、弱引用(Weak Reference)

          被弱引用關聯的物件只能生存到下一次GC發生之前。即每次必被回收。

    d、虛引用(Phantom Reference)

          幽靈引用或者幻影引用,一個物件是否有虛引用的存在不會影響到其生存時間,無法通過虛引用獲取物件例項。為一個物件設定虛引用關聯的唯一目的是希望能在這個物件被回收時受到一個系統通知。

(4)finalize

     在根搜尋演算法中,那些不可達的物件,比如上圖中的Object3和Object4,並非是“真正死亡”的,主要看如下兩次標記過程:

      a、當沒有發現引用鏈時,進行第一次標記,此時進行第一次篩選,條件為此物件是否有必要執行finalize方法。當物件沒有覆蓋finalize方法,或者finalize方法已經被JVM呼叫過,此種情況下認為沒有必要執行finalize方法。

      b、如果有必要執行finalize方法,此時物件會被放置在一個F-Queue佇列中,會有一個優先順序比較低的FInalizer執行緒去執行觸發finalize方法。finalize方法是物件真正判定死活的最後一次機會。此時,GC會對佇列中的物件進行第二次標記,如果物件在finalize方法中完成了自救,即和GC Roots建立了通路,則在第二次標記時該物件將被移出回收的集合。否則,只能判定物件死了。

     示例:物件自救:

public class TestFinalizeGC {
	public static TestFinalizeGC obj = null;

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		System.out.println("finalize method executed");
		//完成自救
		TestFinalizeGC.obj = this;
	}
	
	public static void main(String[] args) {
		obj = new TestFinalizeGC();
		obj = null;
		//自救
		System.gc();
	}
}
    執行結果是:finalize method executed

     說明物件可以再GC時完成自救,需要注意的是這種自救只有一次,因為一個物件的finalize方法最多隻會被系統自動呼叫一次。

相關推薦

JVM如何判斷物件""""

     堆中存放著幾乎所有的物件例項,垃圾收集器在堆堆進行回收前,首先要確定這些物件哪些還“活著”,哪些已經“死去”。方法有如下兩種: (1)引用計數法      演算法思想:為物件新增一個引用計數器,每當有一個地方引用該物件時,則該引用計數器值加1,;當引用失效時,則該

BAT面試必問題系列:JVM判斷物件是否已四種垃圾回收演算法總結

JVM系列: 面試題一:判斷物件是否已死 判斷物件是否已死就是找出哪些物件是已經死掉的,以後不會再用到的,就像地上有廢紙、

JVM 判斷物件,實踐驗證GC回收

![](https://img-blog.csdnimg.cn/20210121093315783.png) 作者:小傅哥 部落格:[https://bugstack.cn](https://bugstack.cn) > 沉澱、分享、成長,讓自己和他人都能有所收穫!

JVM----判斷物件是否存活 : 引用計數演算法OR可達性分析演算法?

本篇來自周志明的<<深入理解java虛擬機器>> 在堆裡面存放著Java世界中幾乎所有的物件例項,垃圾收集器在對堆進行回收前,第一件事情就是要確定這些物件之中哪些還“存活”著 ,哪些已經“死去”(即不可能再被任何途徑使用的物件)。 引用計數演算法 很多教科書判斷物

jvm 判斷物件是否已經死亡

如何判斷java物件已經死亡? 容易想到的就是引用計數演算法,就說的是給物件新增一個引用計數器,每當有一個地方引用到他,就加1;引用失效就減1。但是這樣做是有問題的。 看下例子: public class ReferenceCountingGC { public Obj

BAT面試必問題系列:JVM判斷物件是否已四種垃圾回收演算法總結

JVM系列: 面試題一:判斷物件是否已死 判斷物件是否已死就是找出哪些物件是已經死掉的,以後不會再用到的,就像地上有廢紙、

JVM-如何判斷物件存活與否與CMS收集器G1收集器的區別

JVM如何判斷物件存活? 1、計數器 2、可達性分析   (很多主流語言採用這種方法來判斷物件是否存活)   計數器:每當有一個地方引用該物件時,計數器 +1;引用失效則 -1; 優點:實現簡單,判定效率高。 缺點:難解決物件間的相互迴圈引用問題。  

jvm如何判斷物件

在java的垃圾回收中,jvm是如何判斷堆中的物件是否已死呢?主流的判斷方法有兩種。  1.引用計數演算法:   這種演算法的思路是如果某一個物件被別的物件引用,那麼就把他們引用計數器加上1,這樣當進行垃圾回收時如何判斷該引用的數量為0,此時就代表沒有進行任何物件對其進行

JVM 記憶體管理-----JVM如何判斷物件

分享前丟擲幾個問題? ▪ 如何判斷一個物件是否存活著? ▪為什麼java堆記憶體要分代? ▪一個物件從建立到被回收經歷了哪些過程,如果是很大的物件呢? ▪哪些情況會報outofMemoryError,StackOverFlowError? ▪Jvm調優的配置引數,你

JVM判斷物件是否 “存活” 的演算法 —— 可達性分析演算法

在堆中,幾乎存放著所有的物件例項,那麼回收這些物件例項時,我們需要判斷哪些物件是 “已死” 可以回收的,哪些物件是 “存活” 不需要回收的,下面就來介紹一下 JVM 中如何判斷上述問題的。 基本思路 通過一系列的稱為“GC Roots”的物件作為起始點,從這些節點開

JVM學習--垃圾收集器判斷物件存活方法

JVM學習–總索引 文章目錄 JVM學習--垃圾收集器判斷物件存活方法 引用計數法 可達性分析演算法。 JVM學習–垃圾收集器判斷物件存活方法 相比於C++,Java的優點之一就是會對無用的物件進行垃圾回收,

java面試題之什麼是鎖、鎖、餓競態條件?

    死鎖:是指兩個或兩個以上的程序(或執行緒)在執行過程中,因爭奪資源而造成的一種相互等待的現象,若無外力作用,他們將無法推進下去; 活鎖:是指兩個執行緒優先順序相同,都禮讓不走,就這樣一直僵持下去; 餓死:在單執行緒情況下,A、B兩個執行緒,A先執行;A在執行過程中

關於鎖的形象描述

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

JVM--13 【垃圾回收機制】 如何判斷物件是垃圾

一、物件已經死了嗎?           在堆裡面存放著Java世界中幾乎所有的物件例項,垃圾收集器在對堆進行回收前,第一件事情就是確定這些物件之中哪些是“存活”著,哪些已經“死去”(即不可能再被任何途徑使用的物件) 判斷物件是否存活的演算法:引用計數法、可達性分析演算法

JVM學習--垃圾蒐集器判斷物件存活方法

JVM學習–垃圾蒐集器判斷物件存活方法 相比於C++,Java的優點之一就是會對無用的物件進行垃圾回收,減少記憶體溢位的概率。在進行垃圾回收之前,需要判斷物件是否還存活,也就是是否還被引用。 pub

【JavaSE】執行緒的同步鎖,synchronized物件全域性鎖,一個生活的例子解釋。

1.多執行緒為什麼要加鎖? 因為在多執行緒啟動之後,所有執行緒都是無順序任意執行的,甚至幾乎同時訪問同一個資源或者程式碼塊,所以上一個執行緒對資源所做的改變,還沒來得及使用,就有可能被下一個執行緒所覆蓋。 引入鎖的概念,就是為了讓競爭資源在各個執行緒使用的時候

JVM:GC-判斷物件是否可以回收?

今天開始GC,也就是垃圾回收。 GC主要做三個事情: 1、什麼物件可以回收 2、什麼時候進行回收 3、如何回收 jvm裡的垃圾就是物件,指無用的物件,在真正執行垃圾回收前,必須要判斷物件是否是無用,是否可以回收,那麼jvm是如何來判斷一個物件能否回收呢? 今天就來探討一下。 引用計數演算

垃圾回收之判斷物件否需要被回收(根搜尋演算法引用搜索演算法)

根搜尋演算法(JAVA的虛擬機器用的是這個) 可以參考這個 http://blog.csdn.net/qq_15022971/article/details/79162126 引用搜索演算法:是常被初學JAVA者誤解,java的垃圾回收在判斷一個物件是否為可以被回收的物件時,常被誤以為

JVM物件分配GC分佈【JVM

最近在學習java基礎結構,剛好學到了jvm,總結了以下並可以結合思維導圖認識以下Jvm的物件: 棧:什麼是棧? 先說一下棧的資料結構吧,棧它是一種先進後出的資料結構(FILO),跟佇列剛好相反(先進先出FIFO),生活中有哪些例子, 舉個例子 給子彈上膛,上彈的操作就類似於棧的資料結構,先壓入的子彈

jvm記憶體分配及物件建立回收過程

Java歷史 2004.9 jdk1.5 tiger 自動裝箱拆箱,泛型,,註解,列舉,變長引數,增強for迴圈 spring2.x spring4.x 2006 jdk1.6 javaee Javase Javame jdk6 提供指令碼支援 提供編譯