内存泄漏检测库针对Android和Java。
“小不忍则乱大谋。” -本杰明·富兰克林
在你的build.gradle
:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1
}
在您的应用程序
类:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
你是好去!当你的调试版本检测到活动内存泄漏LeakCanary会自动显示一个通知。
很高兴你问!我们写了一篇博客文章正是要回答这个问题。
使用RefWatcher
看,应该是GCed引用:
RefWatcher refWatcher = {...};
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);
LeakCanary.install()
返回配置的预RefWatcher
。它还安装了ActivityRefWatcher
如果活动泄漏后,可以自动检测Activity.onDestroy()
被调用。
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
观看的片段泄漏:
public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}
RefWatcher.watch()
创建一个KeyedWeakReference到监视对象。.hprof
存储应用程序的文件系统上的文件。HeapAnalyzerService
是在一个单独的进程开始,HeapAnalyzer
使用解析堆转储HAHA。HeapAnalyzer
发现KeyedWeakReference
堆转储由于采用了独特的引用键和定位泄漏参考。HeapAnalyzer
计算最短强参考路径到GC罗茨,以确定是否存在泄漏,然后生成引起泄漏的引用链。DisplayLeakService
在应用过程中,和泄漏通知被示出。你可以看到在logcat的泄漏跟踪:
在com.example.leakcanary:1.0:1 com.example.leakcanary.MainActivity渗漏:
* GC线程ROOT的java.lang.Thread。<Java的地方>(命名为“AsyncTask的#1”)
*引用com.example.leakcanary.MainActivity $ 3,本$ 0(匿名类扩展android.os.AsyncTask)
*泄漏com.example.leakcanary.MainActivity实例
*参考键:e71f3bf5-d786-4145-8539-584afaecad1d
*设备:Genymotion通用谷歌Nexus 6 - 5.1.0 - API 22 - 1440x2560 vbox86p
*的Android版本:5.1 API:22
*持续时间:观看= 5086ms,GC = 110毫秒,堆转储= 435ms,分析= 2086ms
你也可以分享泄漏跟踪,并从堆转储文件操作栏菜单。
一旦你有泄漏痕迹,找出哪些路径参考不应该存在。然后弄清楚为什么该引用仍然存在。很多时候,这是一个注册的侦听器应该是未注册的,一个close()方法
是不叫的方法,即持有引用外部类匿名类。如果你不能在你的代码中找出问题,请不要提交问题。相反,创建一个堆栈溢出问题(使用leakcanary标签)。
有许多已经在AOSP以及在制造商实现了固定的一段时间内已知的内存泄漏。当这样的泄漏发生时,有一点你可以做一个应用程序开发人员来修复它。出于这个原因,LeakCanary具有已知的Android泄漏的内置列表忽略:AndroidExcludedRefs.java。
如果你找到一个新的,请创建一个问题,并按照下列步骤操作:
AndroidExcludedRefs.java
。可选:如果你发现一个黑客以清除在Android的早期版本的泄漏,随时记录下来。这是特别重要的Android的新版本。你有机会来帮助发现早期新的内存泄漏,这有利于整个Android社区。
有时漏痕迹是不够的,你需要挖掘与堆转储MAT或YourKit。这里是你如何能找到头部转储泄漏实例:
com.squareup.leakcanary.KeyedWeakReference
关键
领域。KeyedWeakReference
具有键
字段等于由LeakCanary报告的参考键。指涉
的领域KeyedWeakReference
是你的泄漏对象。
该leakcanary-Android的无操作
释放依赖构建只包含LeakCanary
和RefWatcher
类。如果你开始自定义LeakCanary,你需要确保定制只发生在调试版本,因为它可能会引用不存在的类leakcanary-Android的无操作
的依赖。
比方说,你的发布版本声明一个ExampleApplication
类AndroidManifest.xml中
,你的调试版本声明了一个DebugExampleApplication
扩展ExampleApplication
。
在您的共享资源:
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;
}
}
在调试来源:
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
RefWatcher refWatcher = // Build a customized RefWatcher
return refWatcher;
}
}
这样一来,你的发布代码将包含不超过存在于两个空类等参考LeakCanary leakcanary-Android的无操作
的依赖。
DisplayLeakActivity
自带的默认图标和标签,您可以通过提供改变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
<xml version="1.0" encoding="utf-8">
<resources>
<string name="__leak_canary_display_activity_label">MyLeaks</string>
</resources>
DisplayLeakActivity
节省多达7堆转储和泄漏的痕迹在app目录。您可以通过提供改变这个数字R.integer .__ leak_canary_max_stored_leaks
在您的应用程序:
<xml version="1.0" encoding="utf-8">
<resources>
<integer name="__leak_canary_max_stored_leaks">20</integer>
</resources>
可在1.4-SNAPSHOT。
直到参考被认为提供了内存泄漏,您可以更改延迟R.integer.leak_canary_watch_delay_millis
在您的应用程序:
<xml version="1.0" encoding="utf-8">
<resources>
<integer name="leak_canary_watch_delay_millis">1500</integer>
</resources>
默认延迟为5秒。
您可以更改默认行为泄漏跟踪和堆转储上传到您选择的服务器。
创建您自己的AbstractAnalysisResultService
。最简单的方法是延长DisplayLeakService
在调试来源:
public class LeakUploadService extends DisplayLeakService {
@Override protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
if (!result.leakFound || result.excludedLeak) {
return;
}
myServer.uploadLeakBlocking(heapDump.heapDumpFile, leakInfo);
}
}
建立一个自定义RefWatcher
在调试应用程序类:
// ExampleApplication在“自定义定义和使用无操作dependency"
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary () {
return LeakCanary . install(app, LeakUploadService . class, AndroidExcludedRefs . createAppDefaults() . build());
}
}
不要忘记在调试注册服务的AndroidManifest.xml
:
<xml version="1.0" encoding="utf-8">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<application android:name="com.example.DebugExampleApplication">
<service android:name="com.example.LeakUploadService" />
</application>
</manifest>
您也可以上传泄漏痕迹,松弛或HipChat,这里是一个例子。
你可以创建自己的版本ExcludedRefs
忽略你知道是造成泄漏,但你仍然想要忽略具体的参考:
// ExampleApplication在“自定义定义和使用无操作
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()
.instanceField("com.example.ExampleClass", "exampleField")
.build();
return LeakCanary.install(this, DisplayLeakService.class, excludedRefs);
}
}
ActivityRefWatcher
是默认安装和手表的所有活动。您可以自定义安装步骤,使用不同的东西来代替:
// ExampleApplication在“自定义定义和使用无操作
public class DebugExampleApplication extends ExampleApplication {
@Override protected RefWatcher installLeakCanary() {
if (LeakCanary.isInAnalyzerProcess(this)) {
return RefWatcher.DISABLED;
} else {
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults().build();
LeakCanary.enableDisplayLeakActivity(this);
ServiceHeapDumpListener heapDumpListener = new ServiceHeapDumpListener(this, DisplayLeakService.class);
final RefWatcher refWatcher = LeakCanary.androidWatcher(this, heapDumpListener, excludedRefs);
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
public void onActivityDestroyed(Activity activity) {
if (activity instanceof ThirdPartyActivity) {
return;
}
refWatcher.watch(activity);
}
// ...
});
return refWatcher;
}
}
}
查看更新日志。
leakcanary-的Android
是不是在Android Studio中的外部库的列表,但leakcanary分析仪
和leakcanary观察家
在那里:尝试做一个干净的构建
。如果它仍然是一个问题,尝试在命令行建设。错误:包com.squareup.leakcanary不存在
:如果你有其他类型的建设比调试
和释放
,你需要添加一个特定的依赖也为它们(xxxCompile
)。
热门源码