有效避免OOM--合理使用軟引用和弱引用
在JDK 1.2以前的版本中,若一個物件不被任何變數引用,那麼程式就無法再使用這個物件。也就是說,只有物件處於可觸及(reachable)狀態,程式才能使用它。從JDK 1.2版本開始,把物件的引用分為4種級別,從而使程式能更加靈活地控制物件的生命週期。這4種級別由高到低依次為:強引用、軟引用、弱引用和虛引用
StrongReference
強引用是使用最普遍的引用。如果一個物件具有強引用,那垃圾回收器絕不會回收它。當記憶體空間不足,Java虛擬機器寧願丟擲OutOfMemoryError錯誤,使程式異常終止,也不會靠隨意回收具有強引用的物件來解決記憶體不足的問題。,這是java預設的引用型別,如果不特意使用java.lang.ref下的類,那麼程式中的所有引用都是強引用。SoftReference
軟引用要用java.lang.ref.SoftReference來實現,如果一個物件只具有軟引用,則記憶體空間足夠,垃圾回收器就不會回收它;如果記憶體空間不足了,就會回收這些物件的記憶體。只要垃圾回收器沒有回收它,該物件就可以被程式使用。軟引用可用來實現記憶體敏感的快取記憶體。軟引用可以和一個引用佇列(ReferenceQueue)聯合使用,如果軟引用所引用的物件被垃圾回收器回收,Java虛擬機器就會把這個軟引用加入到與之關聯的引用佇列中。
public class SoftTest{
public static void main(String[] args) {
Object ref = new Object();//ref是Object物件的強引用
//將一個軟引用指向物件,此時Object物件有兩個引用
SoftReference<Object> sf = new SoftReference<Object>(ref);
ref = null;//去除物件的強引用
System.gc();//gc只有在記憶體不足是才會回收軟引用物件
}
}
WeakReference
除了通過java.lang.ref.WeakReference來使用弱引用,WeakHashMap同樣也利用了弱引用。 和軟引用不同的是,弱引用一定會被gc回收,不管記憶體是否不足。弱引用與軟引用的區別在於:只具有弱引用的物件擁有更短暫的生命週期。在垃圾回收器執行緒掃描它所管轄的記憶體區域的過程中,一旦發現了只具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體。不過,由於垃圾回收器是一個優先順序很低的執行緒,因此不一定會很快發現那些只具有弱引用的物件。
弱引用可以和一個引用佇列(ReferenceQueue)聯合使用,如果弱引用所引用的物件被垃圾回收,Java虛擬機器就會把這個弱引用加入到與之關聯的引用佇列中。
public class WeakTest{
public static void main(String[] args) {
Object ref = new Object();//ref是Object物件的強引用
//將一個弱引用指向物件,此時Object物件有兩個引用
WeakReference<Object> wf = new WeakReference<Object>(ref);
ref = null;//去除物件的強引用
System.gc();//gc對弱引用物件進行回收
}
}
PhantomReference
幽靈引用,也叫虛引用。java.lang.ref.PhantomReference類中只有一個方法get(),而且幾乎沒有實現,只是返回null。而且這個類只有一個構造器(軟引用和弱引用均有兩個構造器)。“虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用並不會決定物件的生命週期。如果一個物件僅持有虛引用,那麼它就和沒有任何引用一樣,在任何時候都可能被垃圾回收器回收。
虛引用主要用來跟蹤物件被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個區別在於:虛引用必須和引用隊(ReferenceQueue)聯合使用。當垃圾回收器準備回收一個物件時,如果發現它還有虛引用,就會在回收物件的記憶體之前,把這個虛引用加入到與之 關聯的引用佇列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
程式可以通過判斷引用佇列中是否已經加入了虛引用,來了解被引用的物件是否將要被垃圾回收。如果程式發現某個虛引用已經被加入到引用佇列,那麼就可以在所引用的物件的記憶體被回收之前採取必要的行動。
public class PhantomTest{
public static void main(String[] args) {
Object ref = new Object();//ref是Object物件的強引用
//將一個幽靈引用指向物件,PhantomReference必須與ReferenceQueue一同使用
PhantomReference<Object> pf = new PhantomReference<Object>(ref, new ReferenceQueue<Object>());
System.out.println(pf.get());
}
}
android中的應用
在http://blog.csdn.net/robertcpp/article/details/51563318這篇部落格中講過AsyncQueryHandler的使用AsyncQueryHandler的原始碼中為了防止記憶體洩露,使用了WeakReference來儲存mResolver
public abstract class AsyncQueryHandler extends Handler {
private static final String TAG = "AsyncQuery";
private static final boolean localLOGV = false;
private static final int EVENT_ARG_QUERY = 1;
private static final int EVENT_ARG_INSERT = 2;
private static final int EVENT_ARG_UPDATE = 3;
private static final int EVENT_ARG_DELETE = 4;
/* package */ final WeakReference<ContentResolver> mResolver;
ImageLoader使用WeakReference做快取處理public abstract class BaseMemoryCache implements MemoryCache {
/** Stores not strong references to objects */
private final Map<String, Reference<Bitmap>> softMap = Collections.synchronizedMap(new HashMap<String, Reference<Bitmap>>());
......
@Override
protected Reference<Bitmap> createReference(Bitmap value) {
return new WeakReference<Bitmap>(value);
}
基本可以這麼說weakReference一般用來防止記憶體洩漏,要保證記憶體被VM回收
softReference的話,多用作來實現cache機制.
直接使用handler經常看到這樣的提示
The following Handler class should be static or leaks might occur
Handler設定為static,不能訪問外部非static變數
我們可以這樣寫來解決這個問題
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
不會記憶體洩露,Handler中也能訪問到activity中的非靜態變數
歡迎掃描二維碼,關注公眾號
相關文章
- Java 如何有效地避免OOM:善於利用軟引用和弱引用JavaOOM
- 理解Java的強引用、軟引用、弱引用和虛引用Java
- Android效能優化篇:使用軟引用和弱引用Android優化
- Java的強引用、軟引用、弱引用、虛引用Java
- Android開發優化之——使用軟引用和弱引用Android優化
- 【JVM】如何理解強引用、軟引用、弱引用、虛引用?JVM
- Java引用型別解析:掌握強引用、軟引用、弱引用和幻象引用的妙用Java型別
- Java四種引用包括強引用,軟引用,弱引用,虛引用。Java
- 強引用、軟引用、弱引用、幻象引用有什麼區別?
- Java/Android中的強引用、軟引用、弱引用、虛引用JavaAndroid
- java的強引用、軟引用、弱引用、幻象引用,引用佇列總結Java佇列
- Java四大引用詳解:強引用、軟引用、弱引用、虛引用Java
- Java中的四種引用方式(強引用、軟引用、弱引用、虛引用)Java
- 強引用、軟引用、弱引用、幻象引用再不理解就晚了
- Java常見知識點彙總(⑲)——Java中的強引用、弱引用、軟引用、虛引用Java
- Android效能優化之巧用軟引用與弱引用優化記憶體使用Android優化記憶體
- 如何有效的避免OOM,溫故Java中的引用OOMJava
- python3學習筆記之 強引用和弱引用Python筆記
- Java中的弱引用Java
- Java弱引用與WeakHashMapJavaHashMap
- Java中強、軟、弱、虛四種引用詳解Java
- Swift 4 弱引用實現Swift
- Python 弱引用 學習Python
- 理解Java中的弱引用Java
- ios 避免迴圈引用iOS
- python 圖 自身遍歷及弱引用使用Python
- 從原始碼解析 Swift 弱引用原始碼Swift
- weak 弱引用的實現方式
- Java中的弱引用詳解Java
- Swift - 使用 Protocol 避免框架之間迴圈引用SwiftProtocol框架
- Python迴圈引用是什麼?如何避免迴圈引用?Python
- 你並不一定要用弱引用來避免記憶體洩漏記憶體
- 當弱引用物件成為集合元素時物件
- JVM 符號引用和直接引用JVM符號
- 十分鐘理解Java中的弱引用Java
- [譯] 對元素持有弱引用的 Swift 陣列Swift陣列
- C++ 右值引用和左值引用C++
- C++11 左值引用和右值引用與引用摺疊和完美轉發C++