小孩流鼻血吃什么药好好:Leak 内存泄漏检测

Android中的内存泄露检测方案LeakCanary远离OOM - 推酷
Android中的内存泄露检测方案LeakCanary远离OOM
著名的开源组织 Square 开发了一套 Android 和 Java 内存泄露检测库。
千里之堤, 毁于蚁穴。 - 《韩非子&喻老》
为什么我要用 LeakCanary
问得好!因此我们写了一篇博文来专门回答这个问题。
中文翻译如下:
在开发一个涉及到大量使用 Bitmap 的 Android App 中,经常能看到这个错误:
Java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)
at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121)
没人喜欢 OutOfMemoryError
的时候,我们把客户的签名画在一个 Bitmap 缓存上。这个 Bitmap 的大小和屏幕一样大,创建这个对象的时候,经常会引发内存不足的崩溃问题(即 OutOfMemoryError,简称OOM)。
我们尝试了一些方案,不过都没解决问题:
使用 Bitmap.Config.ALPHA_8 属性 (毕竟签名不需要太多彩色,黑色就足够了)。
捕获 OutOfMemoryError,然后触发 GC 再重试 (从 GCUtils 中得到启发)。
那时候还没有像
这种高级货 ╮(╯▽╰)╭ ,我们没想到在 Java heap 之外申请 bitmaps 缓存空间。
路子走错了
事实上 bitmap 的尺寸并不是真正的问题,当内存吃紧的时候,到处都有可能引发 OOM。在创建大对象,比如 bitmap 的时候,更有可能发生。OOM 只是一个表象,更深层次的问题可能是: 内存泄露。
什么是内存泄露?
一些对象有着有限的生命周期。当这些对象所要做的事情完成了,我们希望他们会被回收掉。但是如果有一系列对这个对象的引用,那么在我们期待这个对象生命周期结束的时候被收回的时候,它是不会被回收的。它还会占用内存,这就造成了内存泄露。持续累加,内存很快被耗尽。
比如,当 Activity.onDestroy 被调用之后,activity 以及它涉及到的 view 和相关的 bitmap 都应该被回收。但是,如果有一个后台线程持有这个 activity 的引用,那么 activity 对应的内存就不能被回收。这最终将会导致内存耗尽,然后因为 OOM 而 crash。
排查内存泄露
排查内存泄露是一个全手工的过程,在 Raizlabs 的
系列文章中有详细描述。
以下几个关键步骤:
等统计平台,了解 OutOfMemoryError 情况。
重现问题。为了重现问题,机型非常重要,因为一些问题只在特定的设备上会出现。为了找到特定的机型,你需要想尽一切办法,你可能需要去买,去借,甚至去偷。 当然,为了确定复现步骤,你需要一遍一遍地去尝试。一切都是非常原始和粗暴的。
在发生内存泄露的时候,把内存 Dump 出来。
然后,你需要在
之类的内存分析工具中反复查看,找到那些原本该被回收掉的对象。
计算这个对象到 GC roots 的最短强引用路径。
找出引用路径中的哪个引用是不该有的,然后修复问题。
上面都是什么鬼啊,如果有一个库能在发生 OOM 这一切之前把这些事情全部都搞定,然后你只要修复这些问题就好了,岂不妙哉!
LeakCanary
LeakCanary 是一个在 debug build中用于检测内存泄露的开源 Java 库。
class Cat {
class Box {
Cat hiddenC
class Docker {
Box box = new Box();
Cat schrodingerCat = new Cat();
box.hiddenCat = schrodingerC
Docker.container =
创建一个 RefWatcher 实例,然后让它来监控一个对象的引用情况:
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);
当检测到内存泄露的时候,你会看到一个 leak trace 报告:
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
我们知道你很忙,一大堆新功能等着你去做,所以我们尽可能让这个变得简单。只要一行代码,LeakCanary 就会自动侦测 Activity 的内存泄露:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
然后你就能在通知里边看到一个显示得整齐漂亮的信息:
使用 LeakCanary 之后,我们修复了我们 APP 中相当多的内存泄露。我们甚至发现了 Android SDK 中的一些内存泄露问题。
结果真让人吃惊,现在我们减少了 94% 的由 OOM 导致的 crash。
在你的 build.gradle 中添加项目引用,Gradle 会自动在中央代码库下载,其中 DEBUG 和 RELEASE 使用的不同的包参加编译:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
在你的 Application 类中添加初始化代码:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
这样就搞定了!在 debug build 中,当检测到内存泄露的时候,LeakCanary 会自动显示一条通知。
ProGuard 混淆配置
如果你在 debug build 中使用了 ProGuard,请确保 HAHA 和 LeakCanary 的类不会被混淆,可以在配置文件中添加下面代码:
# LeakCanary
-keep class org.eclipse.mat.** { *; }
-keep class com.squareup.leakcanary.** { *; }
如何使用 LeakCanary
使用 RefWatcher 对象来监视一个引用是否被 GC 回收:
RefWatcher refWatcher = {...};
// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);
LeakCanary.install() returns a pre configured RefWatcher . It also installs an ActivityRefWatcher that automatically detects if an activity is leaking after Activity.onDestroy() has been called.
public class ExampleApplication extends Application {
public static RefWatcher getRefWatcher(Context context) {
ExampleApplication application = (ExampleApplication) context.getApplicationContext();
return application.refW
private RefWatcher refW
@Override public void onCreate() {
super.onCreate();
refWatcher = LeakCanary.install(this);
You could use the RefWatcher to watch for fragment leaks:
public abstract class BaseFragment extends Fragment {
@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
RefWatcher.watch() creates a
to the watched object.
Later, in a background thread, it checks if the reference has been cleared and if not it triggers a GC.
If the reference is still not cleared, it then dumps the heap into a .hprof file stored on the app file system.
HeapAnalyzerService is started in a separate process and HeapAnalyzer parses the heap dump using
HeapAnalyzer finds the KeyedWeakReference in the heap dump thanks to a unique reference key and locates the leaking reference.
HeapAnalyzer computes the shortest strong reference path to the GC Roots to determine if there is a leak, and then builds the chain of references causing the leak.
The result is passed back to DisplayLeakService in the app process, and the leak notification is shown.
如何复制 leak trace
You can see the leak trace in Logcat:
In com.example.leakcanary:1.0:1 com.example.leakcanary.MainActivity has leaked:
* GC ROOT thread java.lang.Thread.&Java Local& (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-4afaecad1d
* Device: Genymotion generic Google Nexus 6 - 5.1.0 - API 22 -
* Android Version: 5.1 API: 22
* Durations: watch=5086ms, gc=110ms, heap dump=435ms, analysis=2086ms
You can also share the leak trace and the heap dump file from the action bar menu .
如何修复内存漏洞
Once you have the leak trace, figure out which reference in the path should not exist. Then figure out why that reference still exists. Often times it's a registered listener that should have been unregistered, a close() method that wasn't called, an anonymous class that holds a reference an outer class. If you cannot figure out an issue in your code, please do not file an issue . Instead, create a
(using the leakcanary tag).
Android SDK 导致的内存泄露
There are a number of known memory leaks that have been fixed over time in AOSP as well as in manufacturer implementations. When such a leak occurs, there is little you can do as an app developer to fix it. For that reason, LeakCanary has a built-in list of known Android leaks to ignore:
If you find a new one, please
and follow these steps:
Provide the entire leak trace information (reference key, device, etc).
Read the AOSP source for that version of Android, and try to figure out why it happens. You can easily navigate through SDK versions
Check if it happens on the latest version of Android, and otherwise use blame to find when it was fixed.
If it's still happening, build a simple repro case
File an issue on
with the leak trace and the repro case
Create a PR in LeakCanary to update AndroidExcludedRefs.java . Optional: if you find a hack to clear that leak on previous versions of Android, feel free to document it.
This is especially important for new releases of Android . You have the opportunity to help detect new memory leaks early on, which benefits the entire Android community.
Sometimes the leak trace isn't enough and you need to dig into the heap dump with
. Here's how you can find the leaking instance in the head dump:
Look for all instances of com.squareup.leakcanary.KeyedWeakReference
For each of these, look at the key field.
Find the KeyedWeakReference that has a key field equal to the reference key reported by LeakCanary.
The referent field of that KeyedWeakReference is your leaking object.
From then on, the matter is in your hands. A good start is to look at the shortest path to GC Roots (excluding weak references).
个性化定制
Customizing and using the no-op dependency
The leakcanary-android-no-op dependency for release builds only contains the LeakCanary and RefWatcher class. If you start customizing LeakCanary, you need to make sure that the customization happens only in debug build, since it will likely reference classes that do not exist in the leakcanary-android-no-op dependency.
Let's say your release build declares an ExampleApplication class in AndroidManifest.xml , and your debug build declares a DebugExampleApplication that extends ExampleApplication .
In your shared sources:
public class ExampleApplication extends Application {
public static RefWatcher getRefWatcher(Context context) {
ExampleApplication application = (ExampleApplication) context.getApplicationContext();
return application.refW
private RefWatcher refW
@Override public void onCreate() {
super.onCreate();
refWatcher = installLeakCanary();
protected RefWatcher installLeakCanary() {
return RefWatcher.DISABLED;
In your debug sources:
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
RefWatcher refWatcher = ? // Build a customized RefWatcher
return refW
That way, your release code will contain no reference to LeakCanary other than the two empty classes that exist in the leakcanary-android-no-op dependency.
Icon and label
DisplayLeakActivity comes with a default icon and label, which you can change by providing R.drawable.__leak_canary_icon and R.string.__leak_canary_display_activity_label in your app:
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&
Stored leak traces
DisplayLeakActivity saves up to 7 heap dumps & leak traces in the app directory. You can change that number by providing R.integer.__leak_canary_max_stored_leaks in your app:
&?xml version=&1.0& encoding=&utf-8&?&
&resources&
&integer name=&__leak_canary_max_stored_leaks&&20&/integer&
&/resources&
Uploading to a server
You can change the default behavior to upload the leak trace and heap dump to a server of your choosing.
Create your own AbstractAnalysisResultService . The easiest way is to extend DisplayLeakService in your debug sources:
public class LeakUploadService extends DisplayLeakService {
@Override protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
if (!result.leakFound || result.excludedLeak) {
myServer.uploadLeakBlocking(heapDump.heapDumpFile, leakInfo);
Build a custom RefWatcher in your debug Application class:
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
return LeakCanary.install(app, LeakUploadService.class, AndroidExcludedRefs.createAppDefaults().build());
Don't forget to register the service in your debug AndroidManifest.xml :
&?xml version=&1.0& encoding=&utf-8&?&
&manifest xmlns:android=&/apk/res/android&
xmlns:tools=&/tools&
&application android:name=&com.example.DebugExampleApplication&&
&service android:name=&com.example.LeakUploadService& /&
&/application&
&/manifest&
You can also upload the leak traces to Slack or HipChat,
Ignoring specific references
You can create your own version of ExcludedRefs to ignore specific references that you know are causing leaks but you still want to ignore:
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()
.instanceField(&com.example.ExampleClass&, &exampleField&)
return LeakCanary.install(this, DisplayLeakService.class, excludedRefs);
Not watching specific activity classes
ActivityRefWatcher is installed by default and watches all activities. You can customize the installation steps to use something different instead:
public class DebugExampleApplication extends ExampleApplication {
protected RefWatcher installLeakCanary() {
if (isInAnalyzerProcess(this)) {
return RefWatcher.DISABLED;
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults().build();
enableDisplayLeakActivity(application);
ServiceHeapDumpListener heapDumpListener = new ServiceHeapDumpListener(application, DisplayLeakService.class);
final RefWatcher refWatcher = androidWatcher(application, heapDumpListener, excludedRefs);
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
public void onActivityDestroyed(Activity activity) {
if (activity instanceof ThirdPartyActivity) {
refWatcher.watch(activity);
return refW
分析解决问题
if leakcanary-android is not in the list of external libraries in Android Studio, but leakcanary-analyzer and leakcanary-watcher are there: try doing a Clean Build . If it's still a problem, try building from the command line.
error: package com.squareup.leakcanary does not exist : if you have other build types than debug and release , you need to add a specific dependency for those too ( xxxCompile ).
LeakCanary: Detect all memory leaks!
Wrangling Dalvik series:
Uploading leak traces to a
Dump the heap on
StackOverflow:
squ.re/leakcanary
squ.re/leakcanary
README.md in Chinese:
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致Android(44)
原文地址:
英语原文:
ava.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Bitmap.java:-2)
at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
at com.squareup.ui.SignView.createSignatureBitmap(SignView.java:121)
没人喜欢OutOfMemoryError
在Square的注册过程中,我们在bitmap上 。这个bitmap和设备的屏幕大小相当,在创建它的时候,我遇到了相当数量的OOM导致的崩溃。
我们试过了几种方法,没有一个解决了我们的问题:
使用Bitmap.Config.ALPHA_8(签名是不需要颜色的)
捕获OutOfMemoryError,触发垃圾回收然后重试几次(从 获得的启发)
我们没有考虑过将bitmap分配在堆内存之外,那个时候 还没出现。
我们看待问题的方式是不对的
bitmap的大小本身不是什么问题。当内存快要满了的时候,OOM随时随地都可能发生。尤其是在创建大对象的时候更容易发生,比如bitmap。OOM一般代表着更深层次的问题:内存泄漏。
什么是内存泄漏?
有些对象只有有限的生命周期。当它们的任务完成之后,它们将被垃圾回收。如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏。随着泄漏的累积,app将消耗完内存。
比如,在Activity.onDestroy()被调用之后,view树以及相关的bitmap都应该被垃圾回收。如果一个正在运行的后台线程继续持有这个Activity的引用,那么相关的内存将不会被回收,这最终将导致OutOfMemoryError崩溃。
寻找内存泄漏
寻找内存泄漏是一个人工操作的过程,在Raizlabs的
系列中描述得很清楚。
下面是关键的步骤:
通过 , , 或者 了解OOM
主动重现问题。你可能需要买或者借或者偷一个遭遇了崩溃的特殊设备(并不是所有的设备上都会发生内存泄漏!)。你还需要找出是什么串在一起导致了内存泄漏。
当OOM出现时进行堆转储(dump the heap)().
使用MAT或YourKit内存检测工具检测内存的变化,并找出哪个对象应该被垃圾回收;
从那个对象到GC roots推断最短的强引用路径;
在路径中找出不存在的引用,并修复
要是有一个库可以为你做完所有的事情,让你专注于修复内存泄漏的问题,那该有多好。
LeakCanary介绍
是一个开源的在debug版本中检测内存泄漏的java库。
让我们来看看一个cait的例子:
class Cat {
class Box {
Cat hiddenC
class Docker {
Box box = new
Cat schrodingerCat =
new Cat();
box.hiddenCat = schrodingerC
Docker.container =
创建一个RefWatcher实例,然后给它一个对象让它观察:
refWatcher.watch(schrodingerCat);
当检测出泄漏的时候,你会自动得到一个漂亮的泄漏线索:
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
我们知道你的时间宝贵,因此我们让它非常好设置。只需几行代码,LeakCanary就能自动检测Activity的泄漏:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
当内存不足时,会有一个通知和良好的展示界面:
在启用LeakCanary之后,我们发现和修复了许多内存泄漏的问题。我们甚至发现了一些。
结果是非常令人惊奇的,我们现在减少了94%的oom崩溃问题。
如果你想终结OOM崩溃,!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:43127次
排名:千里之外
原创:29篇
转载:25篇
评论:22条
(1)(3)(2)(2)(1)(1)(3)(4)(1)(7)(1)(6)(8)(5)(1)(1)(3)(1)(1)(1)使用Xcode Instruments Leak解决内存泄漏问题
时间: 13:59:55
&&&& 阅读:14325
&&&& 评论:
&&&& 收藏:0
标签:  iOS 5.0之后apple引入了Xcode编译器特性ARC(Automatic Reference Counting,自动引用计数)来帮助开发者管理内存,但为了追求app的高性能与减少安装包大小,工作中很多时候需要我们手动管理内存。再牛的开发者也不能保证自己写的code 100%没有内存泄露,出现内存泄露不可怕,可怕的是我们时间与精力花了大把,但内存泄露依旧没解决,即影响了工作效率也影响自己的心情。
  下面就讲解xcode中的内存调试神器---Instruments Leak ,不管是ios开发菜鸟,还是有经验的开发者,使用Instruments Leak调试内存泄露是必备技能之一。
  废话少说,下面开始摊大饼了!!!
   创建一个基于ARC的测试demo,部分测试代码如下:
  以上几行代码作为app代理入口method,IOS开发者应该是最熟悉不过了,由于创建的是手动管理内存工程,内存泄露的code line一眼就可以定位。
  使用Leaks开始动态分析,点击XCode的Product菜单Profile启动Instruments:
   点击Profile Button编译,呵呵,报错了,如果你遇到这种情况也不要紧张,先看下报错信息:&
  MyViewController与MyNavigationController是我在.pch预编译文件中定义的宏:
  为什么正常编译就没问题,在Profile 中就编译通不过了,其实这里并不是你的代码写的有问题,问题出在Profile的一个编译选项上:
  打开工程的Edit Scheme选项
  选择Profile,将Build Configuration设置为Debug,这样在.pch文件中,#ifdef DEBUG 编译条件下定义的宏就生效 了。
  再次选择Profile building,OK, Success !!!
  进入Instruments主页面,选择Leak Logo
  这时Demo程序也运行起来了,工具显示效果如下:
&  红色的柱子表示内存泄露了。怎么通过这个工具看到在哪泄露了呢?
   先在工具栏按下红色的圆形按钮,把工具监视内存的活动停下来。选择Leak,然后点中间十字交叉那,选择Call Tree   
     
  这时候右下角的Call Tree的可选项可以选了。选中Invert Call Tree 和Hide System Libraries,显示如下:
  看到这里,你最想知道的应该是项目中哪里的code内存泄漏了,ok, 下面我们就来定位内存泄漏的code line .
  看上图中红色框中的Symbol Name 列,如果你猜想0xedc00与0xedbda是内存地址,那么已经很接近正确答案了,可是这东西对我来说有卵用。其实玄机就隐藏在这里,Xcode编译项目后,我们会看到一个同名的 dSYM 文件,dSYM 是保存 16 进制函数地址映射信息的中转文件,我们调试的 symbols 都会包含在这个文件中,并且每次编译项目的时候都会生成一个新的 dSYM 文件,关于dSYM更多的细节,我将在后面的blog中说明。回到上面的问题,显示0xedc00与0xedbda是因为我们的工程build settings 的问题,没有生成dSYM 文件,也就无法解析debug&symbols。下面我们就来正确设置dSYM选项:
  设置好之后,重新 profile build一次,这时候内存泄露的具体代码找到了,下面的红色框框里指定了那个方法出现了内存泄露。
  你只要在这些方法上双击,就会跳转到具体的代码,是不是很牛叉。
  解决内存泄漏问题,将创建的vc对象release掉就OK了,再用Instruments Leak工具分析看看,这时候再怎么操作,都没有内存泄露了。表明内存泄露被堵住了。
大饼摊完了,最后附上有兴趣的同学可以研究一下Instruments中其他工具的用法。
  标签:
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!Andorid学习(25)
本文github地址:
square公司出品的Android内存泄漏检测工具,真的是非常好用,该库已经放在了JCenter上面,在Android Studio下,可以在build.gradle下添加依赖,就可以使用:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
然后,在Application的onCreate()方法中,添加下列代码,就可以使用了:
public class MemLeakApplication extends Application {
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
在该demo程序中,在Activity中,调用Handler的post方法,延迟执行一个任务,模拟内存泄漏。这样,当退出Activity时,由于匿名内部类Runnable还未执行完,它持有一个MainActivity的强引用,导致MainActivity生命周期已经结束,但是资源不能释放,造成了内存泄漏。
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
public void run() {
Log.d(TAG, "Hello");
}, 60 * 1000);
当发生内存泄漏的时候,会弹出Dialog,LeakCanary工具会在/storage/sdcard/Download//目录下生成对应的xxxpending.hprof的pending文件,工具会对内存泄漏进行分析,分析成功后,会在通知栏弹出消息,这时候,对应目录下会变成xxx.hprof文件和xxx.hprof.result文件。可以点击Leaks图标或者使用adb shell命令查看具体分析情况。
adb shell am start -n &package-name&/com.squareup.leakcanary.internal.DisplayLeakActivity
但是,有的时候,我们需要对LeakCanary工具的源代码进行修改,以满足我们的需求,所以,接下来,就学习下在已有的AS工程使用LeakCanary工具源代码进行内存泄漏检测分析。
第一步,将LeakCanary源代码clone下来:
git clone :square/leakcanary.git
第二步,进入leakcanary目录:cd leakcanary,然后将应用放在该目录下,本例以我平常的练习应用为例:git clone /YoungBear/Hello.git。
第三步,修改leakcanary的settings.gradle,即Project Settings,将include ':leakcanary-sample'注释掉,然后添加include ':Hello:app'。由于Hello还有一个库mylibrary,所以将include 'Hello:mylibrary'也添加到settings文件中。
include ':leakcanary-watcher'
include ':leakcanary-analyzer'
include ':leakcanary-android'
include ':leakcanary-android-no-op'
include 'Hello:mylibrary'
include ':Hello:app'
这时候,可以在leakcancary目录下的.gitignore文件中,添加Hello目录,即git忽略Hello目录下的所有文件,这样的话,我们就可以自己修改leakcanary库的源代码了,并且可以提交到远程库。
//leakcanary/.gitignore
第四步,由于mylibrary在工程中的路径变化了,所以需要将leakcanary/Hello/app/build.gradle中的dependencies依赖compile project(':mylibrary')改为compile project(':Hello:mylibrary')。
第五步,在leakcanary/Hello/app/build.gradle添加dependencies依赖:compile project(':leakcanary-android')。
第五步,使用Android Studio,File-&New-&Import Project…,选择leakcanary目录下的build.gradle文件,点击OK。顺利的话,会导入成功。
接下来,就和使用jCenter时候一样了,修改Application即可。
另外,可以通过monkey test来指定包名做测试:
adb shell monkey -p com.example.hello -s 500 -v 100000
该命令会每隔500ms执行一个随机动作,共执行10万次。在实际的项目中,这个数量可以更大。当monkey结束后,可以查看内存泄漏情况。
adb shell am start -n com.example.hello/com.squareup.leakcanary.internal.DisplayLeakActivity
我将Hello工程的memory leak 学习上传到github上了,可以clone下来,然后切换到br_leakcanary_source_learn分支:
/YoungBear/Hello.git
git checkout remotes/origin/br_leakcanary_source_learn
至此,我们就可以根据需要,修改leakcanary的源代码了,也可以学习其原理。
专门用一个project,来分析常见的内存泄漏情况。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12574次
排名:千里之外
原创:40篇
转载:12篇
(4)(1)(2)(2)(3)(6)(12)(2)(8)(7)(2)(4)}

我要回帖

更多关于 小孩流鼻血吃什么好 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信