日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java可达性_java垃圾回收机制--可达性算法

發(fā)布時間:2024/7/5 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java可达性_java垃圾回收机制--可达性算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

先說一些題外話,Java虛擬機在執(zhí)行Java程序的過程中會把它所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū),這些區(qū)分為線程私有區(qū)和線程共享區(qū)

1、線程私有區(qū)

a、程序計數(shù)器

記錄正在執(zhí)行的虛擬機字節(jié)碼指令地址。此區(qū)域是是唯一一個在java虛擬機規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。

b、Java虛擬機棧

描述的是Java方法執(zhí)行的內(nèi)存模型,每個方法在執(zhí)行的同時會創(chuàng)建一個棧幀

c、本地方法棧

它與虛擬機棧發(fā)揮的作用是類似的,它們之間的區(qū)別不過是虛擬機棧為虛擬機執(zhí)行java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機使用的Native方法服務(wù)。

2、線程共享區(qū)

a、Java堆

被所有線程共享的一塊內(nèi)存區(qū)域,也是Java虛擬機所管理的內(nèi)存中最大的一塊。

b、方法區(qū)

用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編輯器編譯后的代碼等數(shù)據(jù),雖然Java虛擬機規(guī)范把方法區(qū)描述為堆的一個邏輯部分,但是它卻有一個別名Non-Heap(非堆)

下面開始說正題

目前虛擬機基本都是采用可達性算法,為什么不采用引用計數(shù)算法呢?下面就說說引用計數(shù)法是如何統(tǒng)計所有對象的引用計數(shù)的,再對比分析可達性算法是如何解決引用技術(shù)算法的不足。先簡單說說這兩個算法:

1、引用計數(shù)法(reference-counting):每個對象都有一個引用計數(shù)器,當(dāng)對象被引用一次,計數(shù)器就加1,當(dāng)對象引用時效一次就減,當(dāng)計數(shù)器為0,意味著對象是垃圾對象,可以被GC回收。

2、可達性算法(GC Root Tracing):從GC Root作為起點開始搜索,那么整個連通圖中對象都是活的,對于GC Root無法達到的對象便是垃圾對象,隨時可被GC回收。

采用引用計數(shù)算法的系統(tǒng)只需在每個實例對象創(chuàng)建之初,通過計數(shù)器來記錄所有的引用次數(shù)即可。而可達性算法,則需要再次GC時,遍歷整個GC根節(jié)點來判斷是否回收。

下面通過一段代碼來對比說明:

public classGcDemo {public static voidmain(String[] args) {//分為6個步驟

GcObject obj1 = new GcObject(); //Step 1

GcObject obj2 = new GcObject(); //Step 2

obj1.instance= obj2; //Step 3

obj2.instance = obj1; //Step 4

obj1= null; //Step 5

obj2 = null; //Step 6

}

}classGcObject{public Object instance = null;

}

1、引用計數(shù)算法

如果采用的是引用計數(shù)算法:

再回到前面代碼GcDemo的main方法共分為6個步驟:

Step1:GcObject實例1的引用計數(shù)加1,實例1的引用計數(shù)=1;

Step2:GcObject實例2的引用計數(shù)加1,實例2的引用計數(shù)=1;

Step3:GcObject實例2的引用計數(shù)再加1,實例2的引用計數(shù)=2;

Step4:GcObject實例1的引用計數(shù)再加1,實例1的引用計數(shù)=2;

執(zhí)行到Step 4,則GcObject實例1和實例2的引用計數(shù)都等于2。

接下來繼續(xù)結(jié)果圖:

Step5:棧幀中obj1不再指向Java堆,GcObject實例1的引用計數(shù)減1,結(jié)果為1;

Step6:棧幀中obj2不再指向Java堆,GcObject實例2的引用計數(shù)減1,結(jié)果為1。

到此,發(fā)現(xiàn)GcObject實例1和實例2的計數(shù)引用都不為0,那么如果采用的引用計數(shù)算法的話,那么這兩個實例所占的內(nèi)存將得不到釋放,這便產(chǎn)生了內(nèi)存泄露。

2、可達性算法

這是目前主流的虛擬機都是采用GC Roots Tracing算法,比如Sun的Hotspot虛擬機便是采用該算法。 該算法的核心算法是從GC Roots對象作為起始點,利用數(shù)學(xué)中圖論知識,圖中可達對象便是存活對象,

而不可達對象則是需要回收的垃圾內(nèi)存。這里涉及兩個概念,一是GC Roots,一是可達性。

那么可以作為GC Roots的對象(見下圖):

虛擬機棧的棧幀的局部變量表所引用的對象;

本地方法棧的JNI所引用的對象;

方法區(qū)的靜態(tài)變量和常量所引用的對象;

關(guān)于可達性的對象,便是能與GC Roots構(gòu)成連通圖的對象,如下圖:

從上圖,reference1、reference2、reference3都是GC Roots,可以看出:

reference1-> 對象實例1;

reference2-> 對象實例2;

reference3-> 對象實例4;

reference3-> 對象實例4 -> 對象實例6;

可以得出對象實例1、2、4、6都具有GC Roots可達性,也就是存活對象,不能被GC回收的對象。

而對于對象實例3、5直接雖然連通,但并沒有任何一個GC Roots與之相連,這便是GC Roots不可達的對象,這就是GC需要回收的垃圾對象。

到這里,相信大家應(yīng)該能徹底明白引用計數(shù)算法和可達性算法的區(qū)別吧。

再回過頭來看看最前面的實例,GcObject實例1和實例2雖然從引用計數(shù)雖然都不為0,但從可達性算法來看,都是GC Roots不可達的對象。

總之,對于對象之間循環(huán)引用的情況,引用計數(shù)算法,則GC無法回收這兩個對象,而可達性算法則可以正確回收。

總結(jié)

以上是生活随笔為你收集整理的java可达性_java垃圾回收机制--可达性算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。