如何在Android Studio中使用LeakCanary检测js内存泄露检测工具

主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
CSDN &《程序员》编辑/记者,投稿&纠错等事宜请致邮
你只管努力,剩下的交给时光!
如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。个人网站:。个人QQ群:、
个人大数据技术博客:Android内存泄漏检测小红的测试生涯
& Android内存泄漏检测
上一篇文章提到了android内存泄漏的三种检测方法:
1)dump java heap + memory analysis tool (MAT) ;
2)leakcanary;
3)android studio;
本文简单介绍一下这三种方法。
1. dump java heap + memory analysis tool (MAT)
具体参见《》
2. leakcanary
Leakcanary的使用参见:
工程的build.gradle中添加:
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'
Acitivity中添加:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
使用debug包,build debug app且安装运行app之后,会有Leaks界面自动安装。并且会自动搜集到activity内存泄漏的信息。
如果想监控Fragment的问题、activity更详细的泄漏信息,可以在具体的代码里面启用RefWatcher进行监控。请参考
另外,我编译debug包的时候一直遇到error:Position 1 : Error retrieving parent for item: No resource found that matches the given name ‘android:Theme.Material’.解决方法是设置合适的sdkversion:
compileSdkVersion 22
buildToolsVersion '21.1.2'
minSdkVersion 14
targetSdkVersion 20
3. android studio
安装android studio的最新版本1.5 preview;
android memory中dump java heap,hprof文件会自动打开;
点击右侧的Analyzer Tasks;
勾选“Detect leaked activities”和“find duplicate Strings”,点击绿色的执行,即可看到泄漏的activity;
Current ye@r *
Leave this field emptyLeakCanary:检测所有的内存泄露
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)
没有人喜欢OutOfMemory崩溃
在Square的注册界面,我们使用bitmap缓存绘制客户的签名,使用的bitmap大小等同于屏幕大小,当创建它时,我们有了大量的OOM崩溃。
我们尝试了一些方法,但是没有一个可以解决问题:使用Bitmap.Config.ALPHA_8(签名不需要颜色)。捕获OutOfMemoryError,触发GC并多次重试(灵感来源于GCUtils)。我们没有想过从 堆分配位图,幸运的是,Fresco 也没有。(注:Fresco是Facebook用于图片缓存的开源库,可以关注一些)
我们曾看错了方向
bitmap的大小并不是问题,当内存将要用完的时候,OOM可以随处发生。它们更多的发生在你创建一个像Bitmap这种比较大的对象的情况下。OOM只是一个症状源自于更深层次的问题:内存泄露。
什么是内存溢出?
某些对象生命周期有限,当它们的工作完成以后,将会被回收。如果一个对象在其生命周期结束以后仍被内存中引用,将会导致内存泄露。当泄露积累过多,该应用将耗尽内存。
比如,在Activity.OnDestroy()方法被调用以后,这个activity的各种层级视图和它们关联的位图都应该被回收掉,如果一个后台运行的线程有该activity的引用,activity相对应的内存将不能被回收,这最终会导致OutOfMemoryError崩溃。
追踪内存溢出
追踪内存溢出是一个手动过程, Raizlabs 的 Wrangling Dalvik 对此有很好的描述。
下面是关键步骤:
通过 Bugsnag, Crashlytics,或者 Developer Console 了解内存溢出。
尝试重现该问题。你可能需要通过购买或者借用遇到崩溃问题的特定设备。(并非所有设备都会呈现这些泄漏) !你还需要弄清楚是哪一系列操作触发泄漏,有可能是蛮力。
当泄露发送时,记录堆栈内容(点击此处获取代码)
使用MAT 或者YourKit 查看堆栈内容,并从中找出应该被回收的对象。
计算最短到 GC 根从该对象的强引用路径。
找出哪个引用路径不应该存在,并修复内存溢出问题。
该库会在你遇到OOM的时候完成以上全部操作,这样你就可以专注于解决内存溢出问题了。
LeakCanary简介
LeakCanary是一个可以在你调试的时候检测内存泄露的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);
当检测到泄漏时,您自动获得不错的泄漏痕迹:
* GC ROOT static Docker.container
* references Box.hiddenCat
* leaks Cat instance
我们知道你忙着写功能,所以我们很容易设置。只是一个代码行,LeakCanary 将会自动检测活动泄漏:
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
你会得到一个Notification和一个很好的展示界面:
在使用LeakCanary以后,我们在自己的应用中发现了许多内存泄露问题,我们甚至发现了一些 SDK的内存泄露。
结果是令人惊讶的,我们的OOM错误减少了94%。
如果你想消灭OOM错误,现在就使用 LeakCanary 吧!
本文原创地址:https://blog.csdn.net/lilu_leo/article/details/ 转载请声明。
2015年,开始尝试玩一下微信公众账号:leakcanary下载|Android LeakCanary(检测内存泄漏插件) 最新版 - 河东下载站Android工具:LeakCanary—内存泄露检测神器
时间: 12:30:16
&&&& 阅读:105
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&一、LeakCanary简介LeakCanary是Square公司开源的一个检测内存的泄露的函数库,可以方便地和你的项目进行集成,在Debug版本中监控Activity、Fragment等的内存泄露;LeakCanary集成到项目中之后,在检测到内存泄露时,会发送消息到系统通知栏。点击后打开名称DisplayLeakActivity的页面,并显示泄露的跟踪信息,Logcat上面也会有对应的日志输出。同时如果跟踪信息不足以定位时,DisplayLeakActivity还为开发者默认保存了最近7个dump文件到App的目录中,可以使用MAT等工具对dump文件进行进一步的分析;二、内存泄漏简介在了解了LeakCanary的接入方式后,我们肯定着急想见识见识LeakCanary的威力。在跟大家演示LeakCanary检测和处理构成之前,大家应该明应该对内存泄露有基本的了解和认识;1.为什么会产生内存泄漏?当一个对象不需要使用本该回收时,有另外一个正在使用的对象持有它的引用,从而导致它不能回收停留在堆内存中,这就产生了内存泄漏;2.内存泄露对程序产生的影响?内存泄漏是造成应用程序OOM的主要原因之一。Android系统为每个应用程序分配有限的内存,当应用中内存泄漏较多时,就难免会导致应用所需要的内存超出系统分配限额,从而导致OOM应用Crash;3.Android常见的内存泄露?相信内存泄露对大家都早有耳闻,但是它不像一些Java异常情况,会立即造成程序的Crash,却有让大家比较“陌生”。下面我们就列举出日常开发中常见的内存泄露类型,让大家对内存泄露的认识不仅仅停留在“有所耳闻 ”的层面;&单例造成:由于单例静态特性使得单例的生命周期和应用的生命周期一样长,如果一个对象(如Context)已经不使用了,而单例对象还持有对象的引用造成这个对象不能正常被回收;&非静态内部类创建静态实例造成:在Acitivity内存创建一个非静态内部类单例,避免每次启动资源重新创建。但是因为非静态内部类默认持有外部类(Activity)的引用,并且使用该类创建静态实例。造成该实例和应用生命周期一样长,导致静态实例持有引用的Activity和资源不能正常回收;&Handler造成:子线程执行网络任务,使用Handler处理子线程发送消息。由于handler对象是非静态匿名内部类的对象,持有外部类(Activity)的引用。在Handler-Message中Looper线程不断轮询处理消息,当Activity退出还有未处理或者正在处理的消息时,消息队列中的消息持有handler对象引用,handler又持有Activity,导致Activity的内存和资源不能及时回收;&线程造成:匿名内部类Runnalbe和AsyncTask对象执行异步任务,对当前Activity隐式引用。当Activity销毁之前,任务还没有执行完,将导致Activity的内存和资源不能及时回收;&资源未关闭造成的内存泄露:对于使用了BroadcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄露;三、LeakCanary接入下面我们还是以QProject项目进行演示如何在项目中接入LeakCanary,项目目录如下:1.添加LeakCanary依赖在主项目main模块的build.gradle文件中添加LeakCanary相关依赖;/main/build.gradle文件apply plugin: ‘com.android.application‘
dependencies {
//添加leakcanary相关的依赖
//在release和test版本中,使用的是LeakCanary的no-op版本,也就是没有实际代码和操作的Wrapper版本,只包含LeakCanary和RefWatcher类的空实现,这样不会对生成的APK包体积和应用性能造成影响
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‘
compile project(‘:test‘)
}2.初始化LeakCanary在主项目main模块的QApplication的onCreate()方法中初始化LeakCanary;/main/src/main/java/com/qproject/main/QApplication.java文件public class QAplication extends Application{
public void onCreate() {
super.onCreate();
//初始化LeakCanary
if (LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}OK,到这里我们就完成了一个项目的LeankCanary的简单接入;提示1:集成LeakCanary后,构建和安装apk的时候报错如下:Error:Error converting bytecode to dex:Cause: com.android.dex.DexException: Multiple dex files define Lcom/squareup/leakcanary/LeakCError:Execution failed for task ‘:main:transformClassesWithDexForDebug‘.& com.android.build.api.transform.TransformException: com.mon.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException处理1:添加依赖debugCompile ‘com.squareup.haha:haha:2.0.3‘,修改依赖的版本为1.4-beta2;四、LeakCanary检测通过对一些常见的内存泄露的学习,我们已经对内存泄露有所见闻了。那么下面我们通过LeakCanary工具,让大家感受下它在你的日常开发中的真实存在。我们以常见内存—单例造成的内存泄露为例进行实践;1.单例内存泄露模拟test/src/main/com/qproject/test/TestManager.javapublic class TestManager {
//单例静态特性使得单例的生命周期和应用的生命周期一样长
private static TestM
* 传入的Context的生命周期很重要:
如果传入的是Application的Context,则生命周期和单例生命周期一样长;
如果传入的是Activity的Context,由于该Context和Activity的生命周期一样长,当Activity退出的时候它的内存不会被回收,因为单例对象持有它的引用;
private TestManager(Context context) {
this.context =
public static TestManager getInstance(Context context) {
if (instance == null) {
instance = new TestManager(context);
}test/src/main/com/qproject/test/leakcanary/LeakCanaryActivity.javapublic class LeakCanaryActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leakcanary);
//获取单例对象,退出Activity即可模拟出内存泄露
TestManager testManager = TestManager.getInstance(this);
}2.检测消息通知运行App到LeakCanaryActivit页面并退出,在检测到内存泄露的时候,会发送消息到系统通知栏;&3.查看检测详情点击通知消息,打开名为DisplayLeakActivity的页面,并显示泄漏的跟踪信息;4.查看LogCat日志除了以上泄漏信息的显示,Logcat上面也会有对应的日志输出;//内存泄露对象com.qproject.test.leakcanary.LeakCanaryActivity
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * com.qproject.test.leakcanary.LeakCanaryActivity has leaked:
//static com.qproject.test.TestManager.instance的com.qproject.test.TestManager.context引用了回收的内存对象
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * GC ROOT static com.qproject.test.TestManager.instance
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * references com.qproject.test.TestManager.context
//内存泄露对象大小,Reference Key,Device和Android Version等信息
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * leaks com.qproject.test.leakcanary.LeakCanaryActivity instance
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * Retaining: 46 KB.
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * Reference Key: 3d74d294-70dc--64e656ea86b8
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * Device: Genymotion Android PREVIEW - Google Nexus 5X - 7.0.0 - API 24 -
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * Android Version: 7.0 API: 24 LeakCanary: 1.5 00f37f5
12-25 07:50:51.710 /com.qproject.main D/LeakCanary: * Durations: watch=5038ms, gc=137ms, heap dump=2390ms, analysis=27325ms
//内存泄露对象详细信息
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: * Details:
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: * Class com.qproject.test.TestManager
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
static instance =
(0x12d898f0)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
static $classOverhead = byte[308]@ (0x12d87581)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: * Instance of com.qproject.test.TestManager
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
static instance =
(0x12d898f0)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
static $classOverhead = byte[308]@ (0x12d87581)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
(0x12c76e00)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
shadow$_klass_ = com.qproject.test.TestManager
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
shadow$_monitor_ = 0
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: * Instance of com.qproject.test.leakcanary.LeakCanaryActivity
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
static $classOverhead = byte[009 (0x12d8e001)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mDelegate =
(0x12d35e50)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mEatKeyUpEvent = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mResources = null
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mThemeId =
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mCreated = true
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mFragments =
(0x12d89420)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mHandler =
(0x12d84520)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mNextCandidateRequestIndex = 0
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mOptionsMenuInvalidated = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mPendingFragmentActivityResults =
(0x12d86850)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mReallyStopped = true
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mRequestedPermissionsFromFragment = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mResumed = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mRetaining = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mStopped = true
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mStartedActivityFromFragment = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mStartedIntentSenderFromFragment = false
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mExtraDataMap =
(0x12d86658)
12-25 07:50:51.711 /com.qproject.main D/LeakCanary: |
mActionBar = null
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mActionModeTypeStarting = 0
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mActivityInfo =
(0x12d35dc0)
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mActivityTransitionState =
(0x12d8f0e8)
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mApplication =
(0x12c53e40)
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mCalled = true
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mChangeCanvasToTranslucent = false
12-25 07:50:51.712 /com.qproject.main D/LeakCanary: |
mChangingConfigurations = false
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mComponent =
(0x12d5c070)
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mConfigChangeFlags = 0
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mCurrentConfig =
(0x12d881c8)
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mDecor = null
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mDefaultKeyMode = 0
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mDefaultKeySsb = null
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mDestroyed = true
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mDoReportFullyDrawn = false
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mEatKeyUpEvent = false
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mEmbeddedID = null
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mEnableDefaultActionBarUp = false
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mEnterTransitionListener =
(0x707a4a98)
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mExitTransitionListener =
(0x707a4a98)
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mFinished = true
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mFragments =
(0x12d893f0)
12-25 07:50:51.713 /com.qproject.main D/LeakCanary: |
mHandler =
(0x12d844e0)
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
mHasCurrentPermissionsRequest = false
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
mInstanceTracker =
(0x12d89400)
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
mInstrumentation =
(0x12c5c3e8)
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
(0x12d91078)
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
mLastNonConfigurationInstances = null
12-25 07:50:51.714 /com.qproject.main D/LeakCanary: |
mMainThread =
(0x12c60100)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mManagedCursors =
(0x12d86628)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mManagedDialogs = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mMenuInflater = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mParent = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mReferrer =
(0x12d91238)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mResultCode = 0
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mResultData = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mResumed = false
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mSearchEvent = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mSearchManager = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mStartedActivity = false
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mStopped = true
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mTaskDescription = android.app.ActivityManager$Ta (0x12d84500)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mTemporaryPause = false
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
(0x12c87fe0)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mTitleColor = 0
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mTitleReady = true
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
(0x12d3c0c0)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mTranslucentCallback = null
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mUiThread =
(0x74cf7000)
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mVisibleBehind = false
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mVisibleFromClient = true
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mVisibleFromServer = true
12-25 07:50:51.715 /com.qproject.main D/LeakCanary: |
mVoiceInteractor = null
12-25 07:50:51.716 /com.qproject.main D/LeakCanary: |
(0x12c84d40)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mWindowAdded = true
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mWindowManager =
(0x12d86778)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mInflater =
(0x12d5ef70)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mOverrideConfiguration = null
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mResources =
(0x12d960d8)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
(0x12d894b0)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
mThemeResource =
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
(0x12d82600)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
shadow$_klass_ = com.qproject.test.leakcanary.LeakCanaryActivity
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: |
shadow$_monitor_ =
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: * Excluded Refs:
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Thread:FinalizerWatchdogDaemon (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Thread:main (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Thread:LeakCanary-Heap-Dump (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Class:java.lang.ref.WeakReference (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Class:java.lang.ref.SoftReference (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Class:java.lang.ref.PhantomReference (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Class:java.lang.ref.Finalizer (always)
12-25 07:50:51.717 /com.qproject.main D/LeakCanary: | Class:java.lang.ref.FinalizerReference (always)5.获取dump日志文件如果觉得跟踪信息不足以定位时,DisplayLeakActivity还为开发者默认保存了最近7个dump文件到APP的目录中,可以使用MAT等工具对dump文件进行进一步的分析;vbox86p:/data/data/com.qproject.main/files/leakcanary # ls
_07-50-51_718.hprof _07-50-51_718.hprof.result
D:\&adb pull ./data/data/com.qproject.main/files/leakcanary/_07-50-51_ 718.hprof
[100%] ./data/data/com.qproject.main/f...akcanary/_07-50-51_718.hprofAndroid Studio-&View-&Tool Windows-&Captures,打开Captures窗口,将pull获取的hprof文件剪切到Capture中文件的目录下,双击打开即可;具体的分析过程,这里就不重点讲述,大家去查询MAT相关的资料;五、检测其他对象如果想监听其他的对象(例如Fragment ),可以通过RefWatcher的实例来实现;&六、LeakCanary原理1.RefWatcher.watch()函数会为被监控的对象创建一个KeyedWeakReference弱引用对象,是WeakReference对的子类,增加了键值对信息,后面会根据指定的键key找到弱引用对象;2.在后台线程AndroidWatchExecutor中,检查KeyedWeakReference弱引用是否已经被清楚。如果还存在,则触发一次垃圾回收之后。垃圾回收之后,如果弱引用对象依然存在,说明发生了内存泄露;标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 c 内存泄露检测 的文章

 

随机推荐