java reference详解_Java Reference详解
Reference是java中的引用類(lèi),它用來(lái)給普通對(duì)像進(jìn)行包裝,從而在JVM在GC時(shí),按照引用類(lèi)型的不同,在回收時(shí)采用不同的邏輯。先來(lái)看下這個(gè)類(lèi)的繼承體系:
image.png
在進(jìn)行對(duì)這些子類(lèi)進(jìn)行分析解釋之前,我們先來(lái)看幾個(gè)概念:
對(duì)象的生命周期
image.png
1.創(chuàng)建階段(Created)
在創(chuàng)建階段系統(tǒng)通過(guò)下面的幾個(gè)步驟來(lái)完成對(duì)象的創(chuàng)建過(guò)程
為對(duì)象分配存儲(chǔ)空間
開(kāi)始構(gòu)造對(duì)象
從超類(lèi)到子類(lèi)對(duì)static成員進(jìn)行初始化
超類(lèi)成員變量按順序初始化,遞歸條用超類(lèi)的構(gòu)造方法
子類(lèi)成員變量按順序初始化,子類(lèi)構(gòu)造方法調(diào)用
一旦對(duì)象被創(chuàng)建,并被分派給某些變量賦值,這個(gè)對(duì)象的狀態(tài)就切換到了應(yīng)用階段。下面通過(guò)具體示例看看:
public class GrandParent {
public GrandParent(){
super();
System.out.println("GrandParent 構(gòu)造函數(shù)");
}
{
System.out.println("GrandParent 成員代碼塊");
}
static {
System.out.println("GrandParent 靜態(tài)代碼塊");
}
}
public class Parent extends GrandParent {
public Parent() {
super();
System.out.println("Parent 構(gòu)造函數(shù)");
}
{
System.out.println("Parent 成員代碼塊");
}
static {
System.out.println("Parent 靜態(tài)代碼塊");
}
}
public class Child extends Parent {
public Child() {
super();
System.out.println("Child 構(gòu)造函數(shù)");
}
{
System.out.println("Child 成員代碼塊");
}
static {
System.out.println("Child 靜態(tài)代碼塊");
}
}
child為子類(lèi),parent為child的超類(lèi),GrandParent為超類(lèi)的超類(lèi),當(dāng)我們執(zhí)行
Child child = new Child();
執(zhí)行順序?yàn)?#xff1a;
image.png
當(dāng)我們執(zhí)行
Parent parent = new Parent();
執(zhí)行順序?yàn)?#xff1a;
image.png
從而證明了一個(gè)對(duì)象創(chuàng)建階段的執(zhí)行順序。
2.應(yīng)用階段(In Use)
對(duì)象至少被一個(gè)強(qiáng)引用持有著。即上述例子中的child持有new Child()的強(qiáng)引用。
3.不可見(jiàn)階段(Invisible)
當(dāng)一個(gè)對(duì)象處于不可見(jiàn)階段時(shí),說(shuō)明程序本身不再持有該對(duì)象的任何強(qiáng)引用,雖然這些引用是存在著的。簡(jiǎn)單說(shuō)就是程序的執(zhí)行已經(jīng)超出了該對(duì)象的作用域了。舉例來(lái)說(shuō):
image.png
則在此時(shí)稱(chēng)之為count處于不可視階段。當(dāng)然這種情況編譯器在編譯的過(guò)程中會(huì)直接報(bào)錯(cuò)了。
4.不可達(dá)階段(Unreachable)
對(duì)象處于不可達(dá)階段是指該對(duì)象不再被任何強(qiáng)引用所持有。與"不可見(jiàn)階段"相比,"不可達(dá)階段"是指程序不再持有該對(duì)象的任何強(qiáng)引用,這種情況下,該對(duì)象仍可能被JVM等系統(tǒng)下的某些已裝載的靜態(tài)變量或線(xiàn)程或JNI等強(qiáng)引用持有著,這些特殊的強(qiáng)引用被稱(chēng)為"GC root"。存在著這些GC root會(huì)導(dǎo)致對(duì)象的內(nèi)存泄露情況,無(wú)法被回收。
5.收集階段(Collected)
當(dāng)垃圾回收器發(fā)現(xiàn)該對(duì)象已經(jīng)處于"不可達(dá)階段"并且垃圾回收起已經(jīng)對(duì)該對(duì)象的內(nèi)存空間重新分配做好準(zhǔn)備時(shí),則對(duì)象進(jìn)入了"收集階段"。如果該對(duì)象已經(jīng)重寫(xiě)了finalize()方法,則會(huì)去執(zhí)行該方法的終端操作。這里要注意盡量不要重載finalize()方法,原因有兩點(diǎn):
會(huì)影響JVM的對(duì)象分配于回收速度
在分配該對(duì)象時(shí),JVM需要在垃圾回收器上注冊(cè)該對(duì)象,以便在回收時(shí)能夠執(zhí)行該重載方法;在該方法執(zhí)行時(shí)需要消耗CPU時(shí)間且在執(zhí)行完該方法后才會(huì)重新執(zhí)行回收操作,即至少需要垃圾回收器對(duì)該對(duì)象執(zhí)行兩次GC。
可能造成該對(duì)象的再次"復(fù)活"
在finalize()方法中,如果有其它的強(qiáng)引用再次持有該對(duì)象。則會(huì)導(dǎo)致對(duì)象的狀態(tài)由" 收集階段"又重新變?yōu)?#34;應(yīng)用階段"。這個(gè)已經(jīng)破壞了Java對(duì)象的生命周期進(jìn)程,且復(fù)活的對(duì)象不利于后續(xù)代碼管理。
終結(jié)階段(Finished)
當(dāng)對(duì)象執(zhí)行完finalize()方法后處于不可達(dá)狀態(tài)時(shí),則該對(duì)象進(jìn)入終結(jié)狀態(tài)。在該階段是等待垃圾回收器對(duì)該對(duì)象空間進(jìn)行回收。
對(duì)象空間重分配階段(De-allocated)
垃圾回收器對(duì)該對(duì)象的所占用的內(nèi)存空間進(jìn)行回收或者再分配,則該對(duì)象測(cè)底消失了,稱(chēng)之為"對(duì)象空重新分配階段"
對(duì)象可達(dá)性判斷
jvm 發(fā)生gc時(shí),判斷一個(gè)對(duì)象是否存在引用,都是從根結(jié)合引用開(kāi)始去標(biāo)識(shí),往往到達(dá)一個(gè)對(duì)象的引用路徑會(huì)很多,如下圖:
image.png
那么垃圾回收時(shí)會(huì)依據(jù)兩個(gè)原則來(lái)判斷對(duì)象的可達(dá)性:
單一路徑中,以最弱的引用為準(zhǔn)
多路徑中,以最強(qiáng)的引用為準(zhǔn)
例如Obj4的引用,存在:1>6、2>5、3>4,那么從根對(duì)象到Obj4的最強(qiáng)引用為2>5,因?yàn)樗鼈兌际菑?qiáng)引用。如果僅僅村子一個(gè)路徑對(duì)Obj4有引用時(shí),比如Obj4有引用時(shí),比如現(xiàn)在只剩下1>6,那么根對(duì)象到Obj4的引用以最弱的為準(zhǔn)。是軟引用。Obj4就是softly-reachable對(duì)象。
強(qiáng)引用(StrongReference)
強(qiáng)引用就是我們平時(shí)創(chuàng)建對(duì)象,創(chuàng)建數(shù)組時(shí)的引用。強(qiáng)引用在任何時(shí)候都不會(huì)被GC回收掉。例如
Parent parent = new Parent();
軟引用(SoftReference)
軟引用是在系統(tǒng)發(fā)生OOM之前才被JVM回收掉。軟引用常被用來(lái)對(duì)于內(nèi)存敏感的緩存。
弱引用(WeakReference)
一旦JVM執(zhí)行GC,弱引用就會(huì)被回收掉。
(虛引用)PhantomReference
虛引用主要作為其指向referent被回收時(shí)的一種通知機(jī)制。
總結(jié)
通過(guò)對(duì)SoftReference,WeakReference,PhantomReference,可以看出JDK提供這些類(lèi)型的reference 主要是用來(lái)和GC交互的,根據(jù)reference的不同,讓JVM采用不同策略來(lái)進(jìn)行對(duì)對(duì)象的回收(reclaim)。softly-reachable的referent在保證在OutOfMemoryError之前回收對(duì)象,weakly-reachable的referent在發(fā)生GC時(shí)就會(huì)被回收,。
總結(jié)
以上是生活随笔為你收集整理的java reference详解_Java Reference详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: gradle 指定java版本_Ecli
- 下一篇: java自带的xml解析_Java自带的