本文原地址,非常不錯的文章
- 集合類泄漏
集合類如果僅僅有添加元素的方法,而沒有相應的刪除機制,導致內存被佔用。如果這個集合類是全局性的變量 (比如類中的靜態屬性,全局性的 map 等即有靜態引用或 final 一直指向它),那麼沒有相應的刪除機制,很可能導致集合所佔用的內存只增不減。比如上面的典型例子就是其中一種情況,當然實際上我們在項目中肯定不會寫這麼 2B 的代碼,但稍不注意還是很容易出現這種情況,比如我們都喜歡通過 HashMap 做一些緩存之類的事,這種情況就要多留一些心眼。
單例造成的內存泄漏
由於單例的靜態特性使得其生命週期跟應用的生命週期一樣長,所以如果使用不恰當的話,很容易造成內存泄漏。比如下面一個典型的例子,public class AppManager { private static AppManager instance; private Context context; private AppManager(Context context) { this.context = context; } public static AppManager getInstance(Context context) { if (instance == null) { instance = new AppManager(context); } return instance; } }
這是一個普通的單例模式,當創建這個單例的時候,由於需要傳入一個Context,所以這個Context的生命週期的長短至關重要:
1.如果此時傳入的是 Application 的 Context,因爲 Application 的生命週期就是整個應用的生命週期,所以這將沒有任何問題。
2.如果此時傳入的是 Activity 的 Context,當這個 Context 所對應的 Activity 退出時,由於該 Context 的引用被單例對象所持有,其生命週期等於整個應用程序的生命週期,所以當前 Activity 退出時它的內存並不會被回收,這就造成泄漏了。
正確的方式應該改爲下面這種方式:public class AppManager { private static AppManager instance; private Context context; private AppManager(Context context) { this.context = context.getApplicationContext(); // 使用Application 的context } public static AppManager getInstance(Context context){ if (instance == null) { instance = new AppManager(context); } return instance; } }
或者這樣寫,連 Context 都不用傳進來了。在你的 Application 中添加一個靜態方法,getContext() 返回 Application 的 context,
public class AppManager {
private static AppManager instance;
private Context context = getApplicationContext();
this.context = MyApplication.getContext();
private AppManager() {
}
// 使用Application 的context
public static AppManager getInstance() {
if (instance == null) {
instance = new AppManager();
}
return instance;
}
/**
* 獲取全局的context
* @return 返回全局context對象
*/
public static Context getContext(){
return context;
}
}
- 匿名內部類/非靜態內部類和異步線程
- 匿名內部類
- Handler 造成的內存泄漏
- 儘量避免使用 static 成員變量
- 避免 override finalize()
- 資源未關閉造成的內存泄漏
- 一些不良代碼造成的內存壓力
- 總結