解讀JVM對象生命周期的幾個階段
在JVM運行空間中,整個JVM對象生命周期大致可以分為7個階段:創(chuàng)建階段(Creation)、應(yīng)用階段(Using)、不可視階段(Invisible)、不可到達階段(Unreachable)、可收集階段(Collected)、終結(jié)階段(Finalized)與釋放階段(Free),這里向大家描述一下除創(chuàng)建階段之外的其他幾個階段。
應(yīng)用階段
這里看一個JVM對象生命周期的第二各階段,當(dāng)對象的創(chuàng)建階段結(jié)束之后,該對象通常就會進入對象的應(yīng)用階段。這個階段是對象得以表現(xiàn)自身能力的階段。也就是說對象的應(yīng)用階段是對象整個生命周期中證明自身“存在價值”的時期。在對象的應(yīng)用階段,對象具備下列特征:
◆系統(tǒng)至少維護著對象的一個強引用(StrongReference);
◆所有對該對象的引用全部是強引用(除非我們顯式地使用了:軟引用(SoftReference)、弱引用(WeakReference)或虛引用(PhantomReference))。
上面提到了幾種不同的引用類型??赡芤恍┳x者對這幾種引用的概念還不是很清楚,下面分別對之加以介紹。在講解這幾種不同類型的引用之前,我們必須先了解一下Java中對象引用的結(jié)構(gòu)層次。
Java對象生命周期引用的結(jié)構(gòu)層次示意如圖2-6所示。
由圖2-6我們不難看出,上面所提到的幾種JVM對象生命周期引用的層次關(guān)系,其中強引用處于頂端,而虛引用則處于底端。下面分別予以介紹。
1.強引用
強引用(StrongReference)是指JVM內(nèi)存管理器從根引用集合(RootSet)出發(fā)遍尋堆中所有到達對象的路徑。當(dāng)?shù)竭_某對象的任意路徑都不含有引用對象時,對這個對象的引用就被稱為強引用。
2.軟引用
軟引用(SoftReference)的主要特點是具有較強的引用功能。只有當(dāng)內(nèi)存不夠的時候,才回收這類內(nèi)存,因此在內(nèi)存足夠的時候,它們通常不被回收。另外,這些引用對象還能保證在Java拋出OutOfMemory異常之前,被設(shè)置為null。它可以用于實現(xiàn)一些常用資源的緩存,實現(xiàn)Cache的功能,保證***限度的使用內(nèi)存而不引起OutOfMemory。再者,軟可到達對象的所有軟引用都要保證在虛擬機拋出OutOfMemoryError之前已經(jīng)被清除。否則,清除軟引用的時間或者清除不同對象的一組此類引用的順序?qū)⒉皇苋魏渭s束。然而,虛擬機實現(xiàn)不鼓勵清除最近訪問或使用過的軟引用。下面是軟引用的實現(xiàn)代碼:
- ……
- importjava.lang.ref.SoftReference;
- …
- Aa=newA();
- …
- //使用a
- …
- //使用完了a,將它設(shè)置為soft引用類型,并且釋放強引用;
- SoftReferencesr=newSoftReference(a);
- a=null;
- …
- //下次使用時
- if(sr!=null){
- a=sr.get();
- }
- else{
- //GC由于內(nèi)存資源不足,可能系統(tǒng)已回收了a的軟引用,
- //因此需要重新裝載。
- a=newA();
- sr=newSoftReference(a);
- }
- ……
軟引用技術(shù)的引進,使Java應(yīng)用可以更好地管理內(nèi)存,穩(wěn)定系統(tǒng),防止系統(tǒng)內(nèi)存溢出,避免系統(tǒng)崩潰(crash)。因此在處理一些占用內(nèi)存較大而且聲明周期較長,但使用并不頻繁的對象時應(yīng)盡量應(yīng)用該技術(shù)。正像上面的代碼一樣,我們可以在對象被回收之后重新創(chuàng)建(這里是指那些沒有保留運行過程中狀態(tài)的對象),提高應(yīng)用對內(nèi)存的使用效率,提高系統(tǒng)穩(wěn)定性。
但事物總是帶有兩面性的,有利亦有弊。在某些時候?qū)浺玫氖褂脮档蛻?yīng)用的運行效率與性能,例如:應(yīng)用軟引用的對象的初始化過程較為耗時,或者對象的狀態(tài)在程序的運行過程中發(fā)生了變化,都會給重新創(chuàng)建對象與初始化對象帶來不同程度的麻煩,有些時候我們要權(quán)衡利弊擇時應(yīng)用。
3.弱引用
弱引用(WeakReference)對象與Soft引用對象的***不同就在于:GC在進行回收時,需要通過算法檢查是否回收Soft引用對象,而對于Weak引用對象,GC總是進行回收。因此Weak引用對象會更容易、更快被GC回收。雖然,GC在運行時一定回收Weak引用對象,但是復(fù)雜關(guān)系的Weak對象群常常需要好幾次GC的運行才能完成。Weak引用對象常常用于Map數(shù)據(jù)結(jié)構(gòu)中,引用占用內(nèi)存空間較大的對象,一旦該對象的強引用為null時,對這個對象引用就不存在了,GC能夠快速地回收該對象空間。與軟引用類似我們也可以給出相應(yīng)的應(yīng)用代碼:
- ……
- importjava.lang.ref.WeakReference;
- …
- Aa=newA();
- …
- //使用a
- …
- //使用完了a,將它設(shè)置為weak引用類型,并且釋放強引用;
- WeakReferencewr=newWeakReference(a);
- a=null;
- …
- //下次使用時
- if(wr!=null){
- a=wr.get();
- }
- else{
- a=newA();
- wr=newWeakReference(a);
- }
- ……
弱引用技術(shù)主要適用于實現(xiàn)無法防止其鍵(或值)被回收的規(guī)范化映射。另外,弱引用分為“短弱引用(ShortWeekReference)”和“長弱引用(LongWeekReference)”,其區(qū)別是長弱引用在對象的Finalize方法被GC調(diào)用后依然追蹤對象?;诎踩紤],不推薦使用長弱引用。因此建議使用下面的方式創(chuàng)建對象的弱引用。
- ……
- WeakReferencewr=newWeakReference(obj);
- 或
- WeakReferencewr=newWeakReference(obj,false);
- ……
4.虛引用
虛引用(PhantomReference)的用途較少,主要用于輔助finalize函數(shù)的使用。Phantom對象指一些執(zhí)行完了finalize函數(shù),并且為不可達對象,但是還沒有被GC回收的對象。這種對象可以輔助finalize進行一些后期的回收工作,我們通過覆蓋Reference的clear()方法,增強資源回收機制的靈活性。虛引用主要適用于以某種比java終結(jié)機制更靈活的方式調(diào)度pre-mortem清除操作。
&注意在實際程序設(shè)計中一般很少使用弱引用與虛引用,使用軟引用的情況較多,這是因為軟引用可以加速JVM對垃圾內(nèi)存的回收速度,可以維護系統(tǒng)的運行安全,防止內(nèi)存溢出(OutOfMemory)等問題的產(chǎn)生。#p#
不可視階段
在一個對象經(jīng)歷了應(yīng)用階段之后,那么該對象便處于JVM對象生命周期的不可視階段,說明我們在其他區(qū)域的代碼中已經(jīng)不可以再引用它,其強引用已經(jīng)消失,例如,本地變量超出了其可視范圍,如下所示。
- ……
- publicvoidprocess(){
- try{
- Objectobj=newObject();
- obj.doSomething();
- }catch(Exceptione){
- e.printStackTrace();
- }
- while(isLoop){//...loopsforever
- //這個區(qū)域?qū)τ趏bj對象來說已經(jīng)是不可視的了
- //因此下面的代碼在編譯時會引發(fā)錯誤
- obj.doSomething();
- }
- }
- ……
如果一個對象已使用完,而且在其可視區(qū)域不再使用,此時應(yīng)該主動將其設(shè)置為空(null)??梢栽谏厦娴拇a行obj.doSomething();下添加代碼行obj=null;,這樣一行代碼強制將obj對象置為空值。這樣做的意義是,可以幫助JVM及時地發(fā)現(xiàn)這個垃圾對象,并且可以及時地回收該對象所占用的系統(tǒng)資源。
不可到達階段
處于JVM對象生命周期不可到達階段的對象,在虛擬機所管理的對象引用根集合中再也找不到直接或間接的強引用,這些對象通常是指所有線程棧中的臨時變量,所有已裝載的類的靜態(tài)變量或者對本地代碼接口(JNI)的引用。這些對象都是要被垃圾回收器回收的預(yù)備對象,但此時該對象并不能被垃圾回收器直接回收。其實所有垃圾回收算法所面臨的問題是相同的——找出由分配器分配的,但是用戶程序不可到達的內(nèi)存塊。
可收集階段、終結(jié)階段與釋放階段
JVM對象生命周期的***一個階段是可收集階段、終結(jié)階段與釋放階段。當(dāng)對象處于這個階段的時候,可能處于下面三種情況:
(1)垃圾回收器發(fā)現(xiàn)該對象已經(jīng)不可到達。
(2)finalize方法已經(jīng)被執(zhí)行。
(3)對象空間已被重用。
當(dāng)對象處于上面的三種情況時,該對象就處于可收集階段、終結(jié)階段與釋放階段了。虛擬機就可以直接將該對象回收了。
【編輯推薦】
- 解讀JVM對象生命周期之創(chuàng)建階段
- Tomcat配置JVM參數(shù)巧妙方法
- JVM基礎(chǔ):解析JVM分代垃圾回收策略
- JVM for Linux JIT診斷技術(shù)簡介
- 巧解IBM JVM for Linux onPOWER性能調(diào)優(yōu)