Java對象是否存活的判斷算法——根搜索算法。
這個(gè)算法的思路其實(shí)很簡單湃窍,它把內(nèi)存中的每一個(gè)對象都看作一個(gè)節(jié)點(diǎn)姑食,并且定義了一些對象作為根節(jié)點(diǎn)“GC Roots”。如果一個(gè)對象中有另一個(gè)對象的引用荐健,那么就認(rèn)為第一個(gè)對象有一條指向第二個(gè)對象的邊,如下圖所示琳袄。JVM會(huì)起一個(gè)線程從所有的GC Roots開始往下遍歷江场,當(dāng)遍歷完之后如果發(fā)現(xiàn)有一些對象不可到達(dá),那么就認(rèn)為這些對象已經(jīng)沒有用了窖逗,需要被回收址否。
四種作為GC Roots的對象==>
1、虛擬機(jī)棧中的引用的對象碎紊,我們在程序中正常創(chuàng)建一個(gè)對象佑附,對象會(huì)在堆上開辟一塊空間,同時(shí)會(huì)將這塊空間的地址作為引用保存到虛擬機(jī)棧中矮慕,如果對象生命周期結(jié)束了帮匾,那么引用就會(huì)從虛擬機(jī)棧中出棧,因此如果在虛擬機(jī)棧中有引用痴鳄,就說明這個(gè)對象還是有用的,這種情況是最常見的缸夹。
2痪寻、我們在類中定義了全局的靜態(tài)的對象,也就是使用了static關(guān)鍵字虽惭,由于虛擬機(jī)棧是線程私有的橡类,所以這種對象的引用會(huì)保存在共有的方法區(qū)中,顯然將方法區(qū)中的靜態(tài)引用作為GC Roots是必須的芽唇。
3顾画、常量引用,就是使用了static final關(guān)鍵字匆笤,由于這種引用初始化之后不會(huì)修改研侣,所以方法區(qū)常量池里的引用的對象也應(yīng)該作為GC Roots。
4炮捧、使用JNI技術(shù)時(shí)庶诡,有時(shí)候單純的Java代碼并不能滿足我們的需求,我們可能需要在Java中調(diào)用C或C++的代碼咆课,因此會(huì)使用native方法末誓,JVM內(nèi)存中專門有一塊本地方法棧扯俱,用來保存這些對象的引用,所以本地方法棧中引用的對象也會(huì)被作為GC Roots喇澡。