WeakReference wr = new WeakReference(obj);
if (wr.get()==null) {
System.out.println("obj 已經被清除了 ");
} else {
java.lang.ref.SoftReference
所有Soft Reference到的對象保證會在java虛擬機發生OutOfMemoryError 前被清除。Soft Reference 雖然和 Weak Reference 很類似,但是用途卻不同。SoftReference 常被用來實現 object-cache (memory-sensitive caches)之用的。 被 Soft Reference 指到的對象,即使沒有任何 Direct Reference,也不會被清除。一直要到 JVM 內存不足時且 沒有 Direct Reference 時纔會清除,如此一來 SoftReference 不但可以把對象 cache 起來,也不會造成內存不足的錯誤 (OutOfMemoryError)。
public(公衆) class ReferenceQueue
extends(擴充) Object
Reference(提及) queues(行列), to which registered(已註冊的) reference objects are appended(附加) by the garbage(垃圾) collector(收藏家) after the appropriate(適當的) reachability changes(改變) are detected(檢測到的).
由於作爲key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作
爲key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object
,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相
同,即obj1.equal
s(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一
定不同,如果兩個不同對象的hashCode相同,這種現象稱爲衝突,衝突會導致操作哈希表的
時間開銷增大,所以儘量定義好的hashCode()方法,能加快哈希表的操作。
get方法返回null),要避免這種問題,只需要牢記一條:要同時複寫equals方法和
hashCode方法,而不要只寫其中一個。
Hashtable是同步的。
transient變量不能是final和static的
class Outer{
int i;
class Inner{
class InnerInner{
void Test(){
Outer.this.i=1;
}
}
}
}
圖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);
Soft References 應用實例
下面以在基於web的應用程序中使用soft references爲例,來說明Java對象引用與JVM的內存管理器進行交互的原理。
當用戶打開某一web頁時,applet代碼獲得圖片並且得到顯示。如果在代碼中同時創建了該圖片對象的soft references,那麼當用戶離開該web頁時,內存管理器對圖片所分配的內存是否回收做出選擇。當用戶返回該web頁時,在applet代碼中使用SoftReference.get方法就會得到圖片才內存中是否仍存在的消息。如果在內存管理器中未創建該圖片,在web頁上會很快得到顯示;否則,applet代碼就會重新獲取。
下面是Example.java的完整源代碼。
import java.awt.Graphics;
import java.awt.Image;
import java.applet.Applet;
import java.lang.ref.SoftReference;
public class Example extends Applet {
SoftReference sr = null;
public void init() {
System.out.println("Initializing");
}
public void paint(Graphics g) {
Image im = (sr == null) ? null : (Image)(sr.get());
if (im == null) {
System.out.println("Fetching image");
im = getImage(getCodeBase(),"yundong.gif");
sr = new SoftReference(im);
}
System.out.println("Painting");
g.drawImage(im, 25, 25, this);
g.drawString("運動之美",20,20);
im = null;
/* Clear the strong reference to the image */
}
public void start() {
System.out.println("Starting");
}
public void stop() {
System.out.println("Stopping");
}
}
在上面的代碼中,對象image是一個圖片對象,傳遞給一個SoftReference對象sr。其中image對象是sr的指示對象,sr中的引用域是從次引用(soft reference)到 image。
Weak References分析
對於一個穩定的對象,比如說線程類對象,當需要獲取外部數據時,在程序中應用weak references是非常理想的。如果利用引用隊列創建了某一線程的weak reference,那麼當線程不再具有強獲取能力時,應用程序得到通知,根據此通知,應用程序才能執行相關數據對象的清除工作。
當內存管理器未發現strong references 和 soft references 時,我們稱對象具有弱獲取能力,即在到達該對象的路徑中至少包含一個weak reference。程序中weak references被清除一段時間後,弱獲取對象被收尾器收集。由此也可以看出,soft reference和weak reference之間的區別在於,應用soft reference時,內存管理器利用算法決定是否創建弱獲取對象,而應用weak reference時,內存管理器必須創建次獲取對象。
引用對象鏈
當到達某一對象的路徑中含有多個引用對象時,就構成了引用對象鏈。內存管理器按照由強到弱的順序處理引用對象,具體處理步驟包括:Soft references、 Weak references、Finalization、Phantom references和創建對象五個部分。
當內存管理器未發現前三種對象引用時,我們稱對象具有虛獲取能力,即在到達該對象的路徑中至少包含一個phantom reference。虛引用對象直接被收尾器收集,而不被重新創建。當內存管理器發現只有phantom references時,對象就將處於等候phantom reference狀態,應用程序向引用隊列發出通知,然後對虛引用對象調用clear()方法,將其引用域設置爲null,最後對不可獲取對象執行收集清除處理任務。
通常,對象所具有的獲取能力與引用對象集合直接路徑中的最弱連接者相同。據此可以看出:
圖2(a)中,虛引用對象具有強獲取能力,其它對象均具虛獲取能力;
(b)中虛引用對象和弱引用對象均具強獲取能力,故次引用對象和對象集合具有若獲取能力;
(c)中虛引用對象、弱引用對象和次引用對象均具強獲取能力,那麼對象集合則具次獲取能力。
圖2 引用對象鏈
小結
● 引用對象API是Java2平臺中的特色之一。
● 在程序中使用引用對象API不但可以在一定程度上控制內存管理器,實現內存自動管理,還可以提高程序的穩定性和安全性。
● 引用對象鏈中各個對象的獲取能力與整個鏈相關。