實操 MAT:
androidProfile進行headdump
命令行導出快照
然后MAT進行配對
原理:
GC回收機制,某對象不再持有任何的引用的時候才會回收
問:如果某對象被別的對象引用了卑硫,就不能被GC回收
否再登,軟引用米丘、虛引用玩徊、弱引用——》用來避免內(nèi)存過度消耗以及容易內(nèi)存泄漏的
該對象一直往上追溯引用,能追溯到GC Root 引用點才能說不被GC回收
可以作為GC Root 引用點的:(產(chǎn)生內(nèi)存泄漏)
JAVAStack中引用的對象
方法區(qū)中的靜態(tài)引用指向?qū)ο?br>
方法區(qū)常量引用指向的對象
Native方法中JNI引用的對象
Tread--活著的對象
例子
1.單例導致內(nèi)存泄漏
單例模式中的靜態(tài)方法使用 Context奕枝,會導致靜態(tài)單例會繼續(xù)持有Activity引用哥谷,導致無法釋放
//修改
context = context.getApplicationContext();
2.靜態(tài)變量導致內(nèi)存泄露
生命周期不一致導致內(nèi)存泄漏
優(yōu)化修改:
進行少的使用岸夯,或者在適當?shù)奈恢弥刂脼閚ull
3.非靜態(tài)內(nèi)部類導致內(nèi)存泄露
Handler、Thread们妥、AsyncTask
msg持有Handler猜扮,mHandler 會作為成員變量保存在發(fā)送的消息 msg 中,msg就間接持有Activity王悍,導致Activity推出后破镰,Looper還是在輪詢,導致無法釋放Activity,進而引起內(nèi)存泄漏鲜漩。
最后別忘了mHandler.removeCallbacksAndMessages源譬。
優(yōu)化修改:
private static class MyHandler extends Handler {
private WeakReference<MainActivity> activityWeakReference;
public MyHandler(MainActivity activity) {
activityWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = activityWeakReference.get();
if (activity != null) {
if (msg.what == 1) { // 做相應(yīng)邏輯
} }
}}
}
4.未取消注冊或回調(diào)導致內(nèi)存泄露
例如廣播和Retrofit+RxJava
5.Timer 和 TimerTask 導致內(nèi)存泄露
cancel 掉 Timer 和 TimerTask
6.集合中的對象未清理造成內(nèi)存泄露
7.資源未關(guān)閉或釋放導致內(nèi)存泄露
8.屬性動畫造成內(nèi)存泄露
9.WebView 造成內(nèi)存泄露
總結(jié):
構(gòu)造單例的時候盡量別用 Activity 的引用;
靜態(tài)引用時注意應(yīng)用對象的置空或者少用靜態(tài)引用;
使用靜態(tài)內(nèi)部類+軟引用代替非靜態(tài)內(nèi)部類;
及時取消廣播或者觀察者注冊;
耗時任務(wù)、屬性動畫在 Activity 銷毀時記得 cancel;
文件流孕似、Cursor 等資源及時關(guān)閉;
Activity 銷毀時 WebView 的移除和銷毀踩娘。