其實Android studio自帶的 Profiler 是不錯的,能夠很直觀看到CPU、內存、網絡的變化,可是有時候簡單看看是看不出來內存泄漏的,須要知道具體怎麼去分析android
Android LeakCanary易於集成,自動檢測出內存泄漏,十分好用git
以Android中的靜態變量爲例github
private static Activity sActivity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
sActivity = this;
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
複製代碼
程序是這樣的,第一個Activity跳轉到第二個Activity,而後finish()返回第一個Activity,咱們反覆多作幾回;正常來說第二個Activity會被銷燬的,可是由於被靜態變量引用了,因此應該是沒法被回收的;bash
首先是點擊下面那一欄的Profiler按鈕,可能尚未選擇程序,點擊+添加程序,這一步通常在咱們操做程序前作,否則都沒記錄網絡
Heap Dump 右邊四列的意思分別以下,通常狀況下,若是Shallow Size和Retained Size都很是小而且相等,均可以認爲是已經被回收的對象。app
- Allocations:Java堆中的實例個數
- Native Size:native層分配的內存大小。
- Shallow Size:Java堆中分配實際大小
- Retained Size:這個類的全部實例保留的內存總大小(並不是實際大小)
點擊Heap Dump中的Main2Activity對象,發現右側出現了Instance View,再點擊Instance View中的對象,出現Reference和上圖同樣;Reference顯示對這個Main2Activity對象的引用,大部分都是系統層面的引用,能夠看到第一個是sActivity這個靜態變量的引用,就說明是它引發的內存泄漏;ide
在內存泄漏檢查的過程當中,我發現常常出現過理論上對象確定是被回收了,卻仍保留的狀況。通常狀況下,若是Shallow Size和Retained Size都很是小(好比我測試的一個空的activity,大概是270)而且相等,均可以認爲是已經被回收的對象。由於系統已經不認爲它會被用到,而且沒有給它保留分配的內存。工具
這個東西特別簡單,直接看官網就好了測試
就是GitHub地址:github.com/square/leak…ui
直接集成:
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
// Optional, if you use support library fragments:
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
}
複製代碼
直接在Application中使用,而後運行APP就會自動檢測,檢測到會在另外一個APP上通知,顯示詳情
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
// Normal app init code...
}
}
複製代碼
以匿名內部類爲例,操做流程和以前的例子同樣;正常來說調用了finish()方法,第二個Activity會被銷燬的,可是由於使用了匿名內部類,因此sRunnable會持有Main2Activity的引用,並且sRunnable仍是一個靜態變量,因此會致使Main2Activity不會被回收掉
public class Main2Activity extends AppCompatActivity {
private static Thread sRunnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
sRunnable = new Thread() {
@Override
public void run() {
}
};
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
}
}
複製代碼
運行程序,而後過一下子就會收到提醒,檢測到了內存泄漏,打開看看;大概意思就是說sRunnable這個對象,它引用了Main2Activity,致使了內存泄漏;這個工具的確很是的簡單友好了