1. 程式人生 > 其它 >解析Java物件引用與JVM自動記憶體管理

解析Java物件引用與JVM自動記憶體管理

物件引用應用程式設計介面是JDKTM1.2中新定義的。該應用程式設計介面允許應用程式以物件引用的方式與JVM的記憶體管理器進行互動。當應用程式需管理大量記憶體物件或者在新的Java物件建立之前需刪除原有物件時,Java物件引用應用程式設計介面具有相當大的用途,例如:

● 基於Web的應用程式常常要求顯示大量圖片,當用戶離開某一Web頁時,往往不能確定是否能夠順利的返回。在這種程式中,應用Java物件引用API可以建立這樣一個環境,即當堆記憶體以最小程度執行時,記憶體管理器建立物件。當用戶返回時,應用程式就會重新載入已經建立的圖片。

● 應用物件引用佇列可以建立這樣一個環境,當通過物件引用獲得某一物件時,應用程式得到通知。然後,應用程式就可以對相關物件進行清除操作,同時使這些物件在記憶體管理器中合法化。


記憶體管理器的工作機制


下面將首先介紹未嵌入引用物件時記憶體管理器的工作機制,然後討論引用物件加入之後Java堆發生的變化。

記憶體管理器的作用就是識別程式中不再使用的物件,並且回收其記憶體。

一個Java應用程式由一系列執行緒組成,每個執行緒執行一系列方法,而每個方法通過引數或區域性變數來引用物件。這些引用屬於引用集合中的一部分,直接進入應用程式。另外,引用集合中還包括類庫中定義的靜態引用變數,以及通過Java本地介面(JNI)API獲得的引用。引用集合中的所有引用物件都可以被當前應用程式獲取,而不必被回收。同樣地,這些物件可能包含對其它物件的引用,也可以被應用程式獲取,依此類推。Java堆中的其它物件視為不可獲取的,而所有這些不可獲取的物件在記憶體管理中也是合法的。如果一個不可獲取的物件使用finalize()方法,任務就交給了物件所呼叫的收尾器(finalizer)。在記憶體回收期間,不具有收尾器的不可獲取物件和已經呼叫收尾器的物件被簡單回收。

記憶體回收的演算法是不斷變化的,共性的方面是從引用集合中識別可獲取的物件以及回收被其它物件佔據的記憶體空間。

加入引用物件之後的引用與常規引用的區別在於,引用物件中的引用專門由記憶體管理器來處理。引用物件封裝了其它一些物件的引用,我們稱之為指示物件。在引用物件建立的同時,也就定義了該引用物件的指示物件。


Java物件引用


圖1所示為物件引用應用程式設計介面中定義的類層次。其中SoftReference類、WeakReference類和PhantomReference類中分別定義了三種引用物件以及相應的三種獲取物件的能力。因此按照由強到弱,物件可獲取程度可劃分為如下五種型別:強獲取(strongly reachable)、次獲取(softly reachable)、弱獲取(weakly reachable)、虛獲取(phantomly reachable)和不可獲取(unreachable)。


圖1 物件應用類層次


根據應用程式要求,物件可以是強引用(strong references)、次引用(soft references)、弱引用(weak references)、虛引用(phantom references)的任意組合。為了確定物件的可獲取程度,JVM記憶體管理器從引用集合出發遍尋堆中所有到物件的路徑。當到達某物件的任意路徑都不含有引用物件時,則稱該物件具有強獲取能力;當路徑中含有一個或幾個引用物件時,根據記憶體管理器所查詢的引用物件的型別分別歸為次獲取、弱獲取、虛獲取。

另外,物件引用API中還定義了引用物件佇列(java.lang.ref.ReferenceQueue),這是記憶體管理器對引用物件進行管理的一種簡單資料結構。值得注意的是,在進行引用物件定義時,要求phantom reference物件必須產生於一個引用物件佇列,而soft reference和weak reference物件則無此限制,如:

ReferenceQueue queue = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, queue);