內(nèi)存泄漏和內(nèi)存溢出的關(guān)系
- 內(nèi)存泄漏: 是指申請空間后,在使用完后沒有釋放。
- 內(nèi)存溢出: 程序向系統(tǒng)申請的內(nèi)存超過了內(nèi)存所能分配的大小(OOM)。
- 內(nèi)存泄漏會導致程序運行變慢,影響體驗程度。大量的內(nèi)存泄露會導致內(nèi)存溢出(oom)。
內(nèi)存泄漏的主要原因
- 持有對象的強引用,沒有及時釋放
導致內(nèi)存泄漏的案例分析
- 寫單列工具類,如:
private static WifiUtils mInstant = null; //全局靜態(tài)變量
public static WifiUtils getInstant(Context context) {
if (mInstant == null) {
synchronized (WifiUtils.class) {
if (mInstant == null) {
mInstant = new WifiUtils(context);
}
}
}
return mInstant;
}
上面可能是我們寫的一個獲取單列引用的方法,單獨這樣看應該沒有任何問題。但是當我們在activity中去調(diào)用
WifiUtils.getInstant(this)
這樣就會造成內(nèi)存泄漏了。
1. 原因:
WifiUtils的對象是全局static的,創(chuàng)建后其生命周期是伴隨程序一直存在的。但他保留了activity的一個強引用,所以當activity需退出時,導致無法銷毀或被回收。
2.解決方案
解決的方案很多,這里舉兩種常用的:
( 1 )、把context 改成 context.getApplicationContext()。這樣并不是所以的地方度可以這樣做,但是一般的工具類可以這樣。
(2)、在activity的時候退出,銷毀mInstant對象。android中registerListener和unregisterListener 的做法就和這個一樣。
編碼的時候時刻注意以下容易出現(xiàn)內(nèi)存溢出的情況
1、帶有全局static變量
2、Inner Classes
private static Object inner;
void createInnerClass() {
class InnerClass {
}
inner = new InnerClass();
}
void paly(){
createInnerClass();//創(chuàng)建內(nèi)部類對象
}
3、Anonymous Classes
void startAsyncTask() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
while(true);
}
}.execute();
}
void paly(){
startAsyncTask();//task執(zhí)行任務的時候,activity無法退出,直到任務執(zhí)行結(jié)束
}
4、Threads、TimerTask、Handler 這幾個有點類試,都是在執(zhí)行任務的時候,對activity保持著強引用,所以在退出的時候,要注意銷毀,防止內(nèi)存泄漏。
內(nèi)存泄漏的規(guī)避
內(nèi)存泄漏無疑會給我們的程序帶來諸多的問題。但是,只要我們記住 "當當前的對象要銷毀時,沒有其他地方對其有強引用,如果有需要先把引用的地方釋放或者銷毀 ” 這樣就會大大減少內(nèi)存泄漏的幾率。