摘要:前兩天,開源了一個內存泄露自動探測神器,它是一個和的內存泄露檢測庫,可以大幅度減少了開發中遇到的問題,對于開發者來說,無疑是個福音,下面對該庫的進行簡單的翻譯小漏不補沉大船。隨著時間過去越來越多熟知的內存泄露問題被制造商在開源項目中修復。
前兩天,Square開源了一個內存泄露自動探測神器——LeakCanary,它是一個Android和Java的內存泄露檢測庫,可以大幅度減少了開發中遇到的OOM問題,對于開發者來說,無疑是個福音,下面對該庫的readme進行簡單的翻譯:
“A small leak will sink a great ship.” - Benjamin Franklin
小漏不補沉大船。——本杰明 富蘭克林
在項目的build.gradle文件添加:
dependencies { debugCompile "com.squareup.leakcanary:leakcanary-android:1.3" releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:1.3" }
在Application類添加:
public class ExampleApplication extends Application { @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }
當在你的debug構建過程中出現內存泄露時,LeakCanary將會自動展示一個通知欄。
為什么我應該使用LeakCanary?問得好!我們正好寫了個博客回答這個問題。
那怎么使用它呢?使用一個RefWatcher觀察引用什么時候應該被GC:
RefWatcher refWatcher = {...}; // We expect schrodingerCat to be gone soon (or not), let"s watch it. refWatcher.watch(schrodingerCat);
LeakCanary.install() 返回一個先前配置的RefWatcher,它也安裝一個ActivityRefWatcher以便在Activity.onDestroy()被調用后自動檢測Activity是否出現泄露。
public class ExampleApplication extends Application { public static RefWatcher getRefWatcher(Context context) { ExampleApplication application = (ExampleApplication) context.getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = LeakCanary.install(this); } }
你可以使用RefWatcher觀察Fragment的內存泄露
public abstract class BaseFragment extends Fragment { @Override public void onDestroy() { super.onDestroy(); RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity()); refWatcher.watch(this); } }How does it work?
1.RefWatcher.watch()創建一個KeyedWeakReference去檢測對象;
2.接著,在后臺線程,它將會檢查是否有引用在不是GC觸發的情況下需要被清除的;
3.如果引用引用仍然沒有被清除,將會轉儲堆到.hprof文件到系統文件中(it them dumps the heap into a .hprof file stored on the app file system.)
4.HeapAnalyzerService是在一個分離的進程中開始的,HeapAnalyzer通過使用HAHA解析heap dump;
5.由于一個特殊的引用key和定位的泄露引用,HeapAnalyzer可以在heap dump中找到KeyedWeakReference;
6.如果有一個泄露,HeapAnalyzer計算到GC Roots的最短的強引用路徑,然后創建造成泄露的引用鏈;
7.結果在app的進程中傳回到DisplayLeakService,并展示泄露的通知消息;
你可以在Logcat上看leak trace:
In com.example.leakcanary:1.0:1 com.example.leakcanary.MainActivity has leaked: * GC ROOT thread java.lang.Thread.(named "AsyncTask #1") * references com.example.leakcanary.MainActivity$3.this$0 (anonymous class extends android.os.AsyncTask) * leaks com.example.leakcanary.MainActivity instance * Reference Key: e71f3bf5-d786-4145-8539-584afaecad1d * Device: Genymotion generic Google Nexus 6 - 5.1.0 - API 22 - 1440x2560 vbox86p * Android Version: 5.1 API: 22 * Durations: watch=5086ms, gc=110ms, heap dump=435ms, analysis=2086ms
你也可以分享leak trace和heap dump文件通過action bar的菜單。
My leak is caused by the SDK implementation!隨著時間過去越來越多熟知的內存泄露問題被制造商在android開源項目中修復。當這樣一個泄露發生時,你能作為一個應用程序開發員來修復它。出于這個原因,LeakCanary有一個內置Android泄露的列表AndroidExcludedRefs.java來監測它,如果你找到一個新的泄露,請用leaktrace創建一個issue,標明設備和Android版本。如果你提供一個heap dump的文件鏈接就更好了。
這是對于新發布的Android版本來說是特別重要的。你有機會更早地幫助檢測新的內存泄露,這有益于整個Android社區。
開發版快照可以通過Sonatype"s snapshots repository找到。
有時leak trace不夠清晰,你需要使用MAT和YourKit深入研究heap dump。這里教你怎樣在head dump找到泄露的實例:
1.找出包com.squareup.leakcanary.KeyedWeakReference下所有實例;
2.對于每個實例,考慮它的key域;
3.找到 KeyedWeakReference 有一個key域等于被LeakCanary報出的引用的key;
4.KeyedWeakReference的referent域是程序中內存泄露的對象;
5.從那時起,問題就轉到你的手上了。一個好的開始是找到最短的GC roots的路徑(排除弱引用)
DisplayLeakActivity自帶一個默認的icon和label,可以通過提供的R.drawable.__leak_canary_icon和R.string.__leak_canary_display_activity_label來修改:
res/ drawable-hdpi/ __leak_canary_icon.png drawable-mdpi/ __leak_canary_icon.png drawable-xhdpi/ __leak_canary_icon.png drawable-xxhdpi/ __leak_canary_icon.png drawable-xxxhdpi/ __leak_canary_icon.png
MyLeaks
###儲存leak traces DisplayLeakActivity可以在你的app目錄保存7個heap dumps和leak traces,你可以在app中通過提供R.integer.__leak_canary_max_stored_leaks的值改變這個數量:20 public class LeakUploadService extends DefaultAnalysisResultService { @Override protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) { if (!result.leakFound || result.excludedLeak) { return; } myServer.uploadLeakBlocking(heapDump.heapDumpFile, leakInfo); } }
###上傳到服務器 你可以改變默認的行為去上傳leak trace并heap dump到你選擇的服務器。 創建你自己的AbstractAnalysisResultService,最容易的方式是在你debug的源碼中繼承DefaultAnalysisResultService:public class ExampleApplication extends Application { public static RefWatcher getRefWatcher(Context context) { ExampleApplication application = (ExampleApplication) context.getApplicationContext(); return application.refWatcher; } private RefWatcher refWatcher; @Override public void onCreate() { super.onCreate(); refWatcher = installLeakCanary(); } protected RefWatcher installLeakCanary() { return RefWatcher.DISABLED; } }確定在你正式發布的Application類中使RefWatcher失效:
public class DebugExampleApplication extends ExampleApplication { protected RefWatcher installLeakCanary() { return LeakCanary.install(app, LeakUploadService.class); } }
在你的debug的Application類創建一個定制的RefWatcher:不要忘記了在你debug的manifest中注冊service:
相關閱讀:內存泄露自動探測神器——LeakCanary
譯者:cfanr
轉載需說明出處:http://navyifanr.github.io/2015/05/09/LeakCanary-project/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/65303.html
摘要:另一種方式就是是一個簡單的,方便的內存檢測工具,可以輕易的發現內存問題,還會生成更加簡單清晰的報告。是一個開源的檢測內存泄露的庫。 在開發Android應用的過程中如果需要處理圖片或者大量數據的時候,就有可能會遇到OOM(java.lang.OutOfMemoryError),一般出現最多的是在創建Bitmap上,也有可能是在內存中處理了大量的數據上。出現OOM應用會直接崩潰,即使沒有...
閱讀 2308·2021-11-24 09:39
閱讀 3038·2021-10-15 09:39
閱讀 3088·2021-07-26 23:38
閱讀 2288·2019-08-30 11:14
閱讀 3409·2019-08-29 16:39
閱讀 1713·2019-08-29 15:23
閱讀 778·2019-08-29 13:01
閱讀 2663·2019-08-29 12:29