java可达性_java垃圾回收机制--可达性算法
先說一些題外話,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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 后序线索树怎样画图_算法新解刘新宇(二)
- 下一篇: hive 时间转字符串_大数据面试杀招—