leakcanary jar包下载只能检测activity的内存泄露吗

Android内存泄漏检测利器:LeakCanary - 知乎专栏
{"debug":false,"apiRoot":"","paySDK":"/api/js","wechatConfigAPI":"/api/wechat/jssdkconfig","name":"production","instance":"column","tokens":{"X-XSRF-TOKEN":null,"X-UDID":null,"Authorization":"oauth c3cef7c66aa9e6a1e3160e20"}}
{"database":{"Post":{"":{"contributes":[{"sourceColumn":{"lastUpdated":,"description":"","permission":"COLUMN_PUBLIC","memberId":1958527,"contributePermission":"COLUMN_PUBLIC","translatedCommentPermission":"all","canManage":true,"intro":"技术小黑屋驻乎办","urlToken":"droidyue","id":26700,"imagePath":"v2-49ce7af5f8b1cf1cffe2af23a2733df1.jpg","slug":"droidyue","applyReason":"0","name":"技术小黑屋 驻乎办","title":"技术小黑屋 驻乎办","url":"/droidyue","commentPermission":"COLUMN_ALL_CAN_COMMENT","canPost":true,"created":,"state":"COLUMN_NORMAL","followers":678,"avatar":{"id":"v2-49ce7af5f8b1cf1cffe2af23a2733df1","template":"/{id}_{size}.jpg"},"activateAuthorRequested":false,"following":false,"imageUrl":"/v2-49ce7af5f8b1cf1cffe2af23a2733df1_l.jpg","articlesCount":18},"state":"accepted","targetPost":{"titleImage":"/v2-0bfd5a81ac8f3846c7bdcfa216e1c736_r.png","lastUpdated":,"imagePath":"v2-0bfd5a81ac8f3846c7bdcfa216e1c736.png","permission":"ARTICLE_PUBLIC","topics":[,3646],"summary":"是什么?一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具为什么需要LeakCanary?因为它简单,易于发现问题,人人可参与。简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等…","copyPermission":"ARTICLE_COPYABLE","translatedCommentPermission":"all","likes":0,"origAuthorId":0,"publishedTime":"T21:55:44+08:00","sourceUrl":"","urlToken":,"id":2571606,"withContent":false,"slug":,"bigTitleImage":false,"title":"Android内存泄漏检测利器:LeakCanary","url":"/p/","commentPermission":"ARTICLE_ALL_CAN_COMMENT","snapshotUrl":"","created":,"comments":0,"columnId":26700,"content":"","parentId":0,"state":"ARTICLE_PUBLISHED","imageUrl":"/v2-0bfd5a81ac8f3846c7bdcfa216e1c736_r.png","author":{"bio":"/","isFollowing":false,"hash":"844aab1ecf","uid":08,"isOrg":false,"slug":"droidyue","isFollowed":false,"description":"/","name":"技术小黑屋","profileUrl":"/people/droidyue","avatar":{"id":"v2-302a166a9e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"memberId":1958527,"excerptTitle":"","voteType":"ARTICLE_VOTE_CLEAR"},"id":589300}],"title":"Android内存泄漏检测利器:LeakCanary","author":"droidyue","content":"是什么?一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具为什么需要LeakCanary?因为它简单,易于发现问题,人人可参与。简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等多个步骤。易于发现问题:在手机端即可查看问题即引用关系,而MAT则需要你分析,找到Path To GC Roots等关系。人人可参与:开发人员,测试测试,产品经理基本上只要会用App就有可能发现问题。而传统的MAT方式,只有部分开发者才有精力和能力实施。如何集成尽量在app下的build.gradle中加入以下依赖 dependencies {\n
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1\n
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1\n
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1\n }\n在Application中加入类似如下的代码public class ExampleApplication extends Application {\n\n
@Override public void onCreate() {\n
super.onCreate();\n
LeakCanary.install(this);\n
}\n}\n到这里你就可以检测到Activity的内容泄露了。其实现原理是设置Application的ActivityLifecycleCallbacks方法监控所有Activity的生命周期回调。内部实现代码为public final class ActivityRefWatcher {\n
private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {\n
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {\n
public void onActivityStarted(Activity activity) {\n
public void onActivityResumed(Activity activity) {\n
public void onActivityPaused(Activity activity) {\n
public void onActivityStopped(Activity activity) {\n
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {\n
public void onActivityDestroyed(Activity activity) {\n
ActivityRefWatcher.this.onActivityDestroyed(activity);\n
private final Application application;\n
private final RefWatcher refWatcher;\n\n
public static void installOnIcsPlus(Application application, RefWatcher refWatcher) {\n
if(VERSION.SDK_INT &= 14) {\n
ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);\n
activityRefWatcher.watchActivities();\n
}\n....\n}\n想要检测更多?首先我们需要获得一个RefWatcher,用来后续监控可能发生泄漏的对象public class MyApplication extends Application {\n
private static RefWatcher sRefWatcher;\n\n\n
@Override\n
public void onCreate() {\n
super.onCreate();\n
sRefWatcher = LeakCanary.install(this);\n
public static RefWatcher getRefWatcher() {\n
return sRefWatcher;\n
}\n}\n监控某个可能存在内存泄露的对象MyApplication.getRefWatcher().watch(sLeaky);\n哪些需要进行监控默认情况下,是对Activity进行了检测。另一个需要监控的重要对象就是Fragment实例。因为它和Activity实例一样可能持有大量的视图以及视图需要的资源(比如Bitmap)即在Fragment onDestroy方法中加入如下实现public class MainFragment extends Fragment {\n
@Override\n
public void onDestroy() {\n
super.onDestroy();\n
MyApplication.getRefWatcher().watch(this);\n
}\n}\n其他也可以监控的对象BroadcastReceiverService其他有生命周期的对象直接间接持有大内存占用的对象(即Retained Heap值比较大的对象)何时进行监控首先,我们需要明确什么是内存泄露,简而言之,某个对象在该释放的时候由于被其他对象持有没有被释放,因而造成了内存泄露。因此,我们监控也需要设置在对象(很快)被释放的时候,如Activity和Fragment的onDestroy方法。一个错误示例,比如监控一个Activity,放在onCreate就会大错特错了,那么你每次都会收到Activity的泄露通知。如何解决常用的解决方法思路如下尽量使用Application的Context而不是Activity的使用弱引用或者软引用手动设置null,解除引用关系将内部类设置为static,不隐式持有外部的实例注册与反注册成对出现,在对象合适的生命周期进行反注册操作。如果没有修改的权限,比如系统或者第三方SDK,可以使用反射进行解决持有关系加入例外有些特殊情况,我们需要忽略一些问题,这时候就需要添加例外规则。比如ExampleClass.exampleField会导致内存泄漏,我们想要忽略,如下操作即可。// ExampleApplication is defined in \"Customizing and using the no-op dependency\"\npublic class DebugExampleApplication extends ExampleApplication {\n
protected RefWatcher installLeakCanary() {\n
ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults()\n
.instanceField(\"com.example.ExampleClass\", \"exampleField\")\n
.build();\n
return LeakCanary.install(this, DisplayLeakService.class, excludedRefs);\n
}\n}\n如何实现的LeakCanary实际上就是在本机上自动做了Heap dump,然后对生成的hprof文件分析,进行结果展示。和手工进行MAT分析步骤基本一致。如何不影响对外版APK是的,这个问题确实值得关注,因为LeakCanary确实是影响程序运行的,尤其是heap dump操作,不过好在这件事Square已经考虑了,即在我们增加依赖时debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' // or 1.4-beta1\nreleaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1\ntestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' // or 1.4-beta1\n其中releaseCompile和testCompile这两个的依赖明显不同于debugCompile的依赖。它们的依赖属于NOOP操作。NOOP,即No Operation Performed,无操作指令。常用的编译器技术会检测无操作指令并出于优化的目的将无操作指令剔除。因而,只要配置好releaseCompile和testCompile的依赖,就无需担心对外版本的性能问题了。注意目前LeakCanary一次只能报一个泄漏问题,如果存在内存泄漏但不是你的模块,并不能说明这个模块没有问题。建议建议将非本模块的泄漏解决之后,再进行检测。我的知乎 Live 推荐Anroid中内存泄漏相关文章","updated":"T13:55:44.000Z","canComment":false,"commentPermission":"anyone","commentCount":4,"collapsedCount":0,"likeCount":35,"state":"published","isLiked":false,"slug":"","lastestTipjarors":[],"isTitleImageFullScreen":false,"rating":"none","titleImage":"/v2-0bfd5a81ac8f3846c7bdcfa216e1c736_r.png","links":{"comments":"/api/posts//comments"},"reviewers":[],"topics":[{"url":"/topic/","id":"","name":"Android"},{"url":"/topic/","id":"","name":"内存泄露"},{"url":"/topic/","id":"","name":"Java"}],"adminClosedComment":false,"titleImageSize":{"width":700,"height":364},"href":"/api/posts/","excerptTitle":"","column":{"slug":"droidyue","name":"技术小黑屋 驻乎办"},"tipjarState":"activated","tipjarTagLine":"真诚赞赏,手留余香","sourceUrl":"","pageCommentsCount":4,"tipjarorCount":0,"annotationAction":[],"hasPublishingDraft":false,"snapshotUrl":"","publishedTime":"T21:55:44+08:00","url":"/p/","lastestLikers":[{"bio":"研发工程师","isFollowing":false,"hash":"fcba0d532b009dade0b20","uid":52,"isOrg":false,"slug":"long-gang-62-42","isFollowed":false,"description":"","name":"隆刚","profileUrl":"/people/long-gang-62-42","avatar":{"id":"335f661c417aa87311ccf","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"爬步的程序猿","isFollowing":false,"hash":"ee8cda9b4a3d","uid":474400,"isOrg":false,"slug":"qiu-zhi-wei-96","isFollowed":false,"description":"","name":"邱智巍","profileUrl":"/people/qiu-zhi-wei-96","avatar":{"id":"02fcababb","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"我头像像屌吗?","isFollowing":false,"hash":"c51ca7c4bcffa1c476be85a","uid":514240,"isOrg":false,"slug":"waylanpunch","isFollowed":false,"description":"以美貌取胜。","name":"Waylan Punch","profileUrl":"/people/waylanpunch","avatar":{"id":"v2-9aaf9b243f06ed13ba7aea","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"","isFollowing":false,"hash":"f71ff3e39c5b2a","uid":16,"isOrg":false,"slug":"JoeWic.Y","isFollowed":false,"description":"只想当好厨子的程序猿","name":"Joe.Y","profileUrl":"/people/JoeWic.Y","avatar":{"id":"1d0bcdc2bf3a1","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},{"bio":"程序员","isFollowing":false,"hash":"d43cebc49409ffb771ded13c4ed5741b","uid":984600,"isOrg":false,"slug":"porify","isFollowed":false,"description":"","name":"Porify","profileUrl":"/people/porify","avatar":{"id":"v2-ecf9e4a16caeafba9c3b5f04","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false}],"summary":"是什么?一言以蔽之:LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具为什么需要LeakCanary?因为它简单,易于发现问题,人人可参与。简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等…","reviewingCommentsCount":0,"meta":{"previous":{"isTitleImageFullScreen":false,"rating":"none","titleImage":"/50/v2-e16e1f7673baf34cac4cf3_xl.jpg","links":{"comments":"/api/posts//comments"},"topics":[{"url":"/topic/","id":"","name":"Git"},{"url":"/topic/","id":"","name":"GitHub"},{"url":"/topic/","id":"","name":"SSH"}],"adminClosedComment":false,"href":"/api/posts/","excerptTitle":"","author":{"bio":"/","isFollowing":false,"hash":"844aab1ecf","uid":08,"isOrg":false,"slug":"droidyue","isFollowed":false,"description":"/","name":"技术小黑屋","profileUrl":"/people/droidyue","avatar":{"id":"v2-302a166a9e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false},"column":{"slug":"droidyue","name":"技术小黑屋 驻乎办"},"content":"git是一款超极优秀的版本控制工具,包括Linus大神的linux项目在内的千千万万的项目在使用。你可以使用Eclipse插件管理,亦可以使用终端工具。git虽然有着svn不能匹及的本地仓库,但是和svn一样,和远程服务器通信也相当常用。常用的pull和push就是比较常见的命令。然后,你是不是觉得从远程拉取(pull)到本地是不是很慢,从本地推到服务器端(push)又是不是很耗时呢,是吧,正所谓人生苦短,赶紧加速你的git吧。修改ssh配置按照下面的内容修改这个文件vim ~/.ssh/configControlMaster auto\n##ControlPath /tmp/%r@%h:%p\nControlPath /tmp/:22\nControlPersist yes\n一些注解ControlMaster auto可以使多个ssh会话共享一个已经存在的连接,如果没有,则自动创建一个连接。ControlPath /tmp/%r@%h:%p可以指定想要共享的连接。%r代表远程登录用户名,一般都为git,%h表示目标主机,%p表示端口。ControlPersist yes 则可以让共享的连接持有处于连接状态。常用的ControlPath下面包含开源中国,github,gitcafe等代码托管。ControlPath /tmp/git@git.oschina.net:22\nControlPath /tmp/:22\nControlPath /tmp/:22\n快来试一试吧,是不是提高了5倍!注:由于网络的情况,结果可能略有不同。已经很快的但没有感觉改善的同学,可以继续读下去。还能更快还有一个能提高50倍的方法,不过对于一般开发者不是很常用,如需了解可以参考我的知乎 Live 推荐","state":"published","sourceUrl":"","pageCommentsCount":0,"canComment":false,"snapshotUrl":"","slug":,"publishedTime":"T22:11:53+08:00","url":"/p/","title":"人生苦短,让你的Git飞起来吧","summary":"git是一款超极优秀的版本控制工具,包括Linus大神的linux项目在内的千千万万的项目在使用。你可以使用Eclipse插件管理,亦可以使用终端工具。git虽然有着svn不能匹及的本地仓库,但是和svn一样,和远程服务器通信也相当常用。常用的pull和push就是比较常见…","reviewingCommentsCount":0,"meta":{"previous":null,"next":null},"commentPermission":"anyone","commentsCount":3,"likesCount":31},"next":null},"annotationDetail":null,"commentsCount":4,"likesCount":35,"FULLINFO":true}},"User":{"droidyue":{"isFollowed":false,"name":"技术小黑屋","headline":"/","avatarUrl":"/v2-302a166a9e_s.jpg","isFollowing":false,"type":"people","slug":"droidyue","bio":"/","hash":"844aab1ecf","uid":08,"isOrg":false,"description":"/","profileUrl":"/people/droidyue","avatar":{"id":"v2-302a166a9e","template":"/{id}_{size}.jpg"},"isOrgWhiteList":false,"badge":{"identity":null,"bestAnswerer":null}}},"Comment":{},"favlists":{}},"me":{},"global":{"experimentFeatures":{"ge3":"ge3_9","ge2":"ge2_1","appStoreRateDialog":"close","nwebStickySidebar":"sticky","qrcodeLogin":"qrcode","favAct":"default","default":"None","mobileQaPageProxyHeifetz":"m_qa_page_nweb","newMore":"new","iOSNewestVersion":"4.2.0","newMobileColumnAppheader":"new_header","newBuyBar":"livenewbuy3","sendZaMonitor":"true","homeUi2":"default","answerRelatedReadings":"qa_recommend_by_algo_related_with_article","wechatShareModal":"wechat_share_modal_show","qaStickySidebar":"sticky_sidebar","androidProfilePanel":"panel_b","liveStore":"ls_a2_b2_c1_f2","zcmLighting":"zcm"}},"columns":{"next":{},"droidyue":{"following":false,"canManage":false,"href":"/api/columns/droidyue","name":"技术小黑屋 驻乎办","creator":{"slug":"droidyue"},"url":"/droidyue","slug":"droidyue","avatar":{"id":"v2-49ce7af5f8b1cf1cffe2af23a2733df1","template":"/{id}_{size}.jpg"}}},"columnPosts":{},"columnSettings":{"colomnAuthor":[],"uploadAvatarDetails":"","contributeRequests":[],"contributeRequestsTotalCount":0,"inviteAuthor":""},"postComments":{},"postReviewComments":{"comments":[],"newComments":[],"hasMore":true},"favlistsByUser":{},"favlistRelations":{},"promotions":{},"switches":{"couldAddVideo":false},"draft":{"titleImage":"","titleImageSize":{},"isTitleImageFullScreen":false,"canTitleImageFullScreen":false,"title":"","titleImageUploading":false,"error":"","content":"","draftLoading":false,"globalLoading":false,"pendingVideo":{"resource":null,"error":null}},"drafts":{"draftsList":[],"next":{}},"config":{"userNotBindPhoneTipString":{}},"recommendPosts":{"articleRecommendations":[],"columnRecommendations":[]},"env":{"edition":{},"isAppView":false,"appViewConfig":{"content_padding_top":128,"content_padding_bottom":56,"content_padding_left":16,"content_padding_right":16,"title_font_size":22,"body_font_size":16,"is_dark_theme":false,"can_auto_load_image":true,"app_info":"OS=iOS"},"isApp":false},"sys":{},"message":{"newCount":0},"pushNotification":{"newCount":0}}利用 LeakCanary 来检查 Android 内存泄漏 - 简书
利用 LeakCanary 来检查 Android 内存泄漏
你被概率性的 OOM 困扰么?有时候,OOM 像幽灵一样,挥之不去,可真想把它揪出来时,又捉之不着。或许,是时候用
来诊断一下了。它是一个用来检查 Android 下内存泄漏的开源库,这篇文章主要介绍其用法、架构和其背后的实现原理。
Square 介绍了开发这个库的原因。他们的一个付款流程里,需要用到用户的签名,他们直接用 Bitmap 来画签名,Bitmap 大小和屏幕分辨率是一样的。问题来了,在试图创建这个 Bitmap 对象时,概率性 OOM 如幽灵般相随。他们试了几个方法:
使用 Bitmap.Config.ALPHA_8 来节省内存
捕获 OutOfMemoryError 异常,调用 gc 清理内存,然后重试几次
最终这些都不起作用。最终他们发现他们在错误的方向上走得太远了。当存在内存泄漏时,可用内存越来越少,这个时候 OOM 可以发生在任何地方,特别是试图创建一些大内存对象,如 Bitmap 的时候。
我们在上一篇文章里介绍了使用
来分析内存泄漏的方法。概括起来核心步骤是:
发生 OOM 或做一些可能存在内存泄漏的操作后,导出 HPROF 文件
利用 MAT 结合代码分析,来发现一些引用异常,比如哪些对象本来应该被回收的,却还在系统堆中,那么它就是内存泄漏
如果有一个工具能自动完成这些事情,甚至在发生 OOM 之前,就把内存泄漏报告给你,那是多么美好的一件事情啊。LeakCanary 就是用来干这个事情的。在测试你的 App 时,如果发生了内存泄漏,状态栏上会有通知告诉你。logcat 上也会有相应的 log 通知你。
!!! notes "启发"
LeakCanary 产生的背后有几个有意思的启发。一是像 Square 这样公司一样会被 OOM 这种问题困扰;二是他们也会犯错,试了几种方法都不起作用;三是他们最终用一个优雅的方式解决了这个问题,并且通过开源库的方式让所有人共享他们的工作成果。
监控 Activity 泄露
我们经常把 Activity 当作为 Context 对象使用,在不同场合由各种对象引用 Activity。所以,Activity 泄漏是一个重要的需要检查的内存泄漏之一。
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);
LeakCanary.install() 返回一个配置好了的 RefWatcher 实例。它同时安装了 ActivityRefWatcher 来监控 Activity 泄漏。即当 Activity.onDestroy() 被调用之后,如果这个 Activity 没有被销毁,logcat 就会打印出如下信息告诉你内存泄漏发生了。
* com.example.leakcanary.MainActivity has leaked:
* GC ROOT thread java.lang.Thread.&Java Local& (named 'AsyncTask #1')
* references com.example.leakcanary.MainActivity$2.this$0 (anonymous class extends android.os.AsyncTask)
* leaks com.example.leakcanary.MainActivity instance
* Reference Key: c4dd-4caf-993b-4b835c255873
* Device: Genymotion generic Google Galaxy Nexus - 4.2.2 - API 17 - 720x1280 vbox86p
* Android Version: 4.2.2 API: 17
* Durations: watch=5100ms, gc=104ms, heap dump=82ms, analysis=3008ms
LeakCanary 自动检测 Activity 泄漏只支持 Android ICS 以上版本。因为 Application.registerActivityLifecycleCallbacks() 是在 API 14 引入的。如果要在 ICS 之前监测 Activity 泄漏,可以重载 Activity.onDestroy() 方法,然后在这个方法里调用 RefWatcher.watch(this) 来实现。
监控 Fragment 泄漏
public abstract class BaseFragment extends Fragment {
public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
当 Fragment.onDestroy() 被调用之后,如果这个 fragment 实例没有被销毁,那么就会从 logcat 里看到相应的泄漏信息。
监控其他泄漏
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(someObjNeedGced);
当 someObjNeedGced 还在内存中时,就会在 logcat 里看到内存泄漏的提示。
集成 LeakCanary 库
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
在 debug 版本上,集成 LeakCanary 库,并执行内存泄漏监测,而在 release 版本上,集成一个无操作的 wrapper ,这样对程序性能就不会有影响。
LeakCanary 流程图
leakcanary
LeakCanary 的机制如下:
RefWatcher.watch() 会以监控对象来创建一个 KeyedWeakReference 弱引用对象
在 AndroidWatchExecutor 的后台线程里,来检查弱引用已经被清除了,如果没被清除,则执行一次 GC
如果弱引用对象仍然没有被清除,说明内存泄漏了,系统就导出 hprof 文件,保存在 app 的文件系统目录下
HeapAnalyzerService 启动一个单独的进程,使用 HeapAnalyzer 来分析 hprof 文件。它使用另外一个开源库 。
HeapAnalyzer 通过查找 KeyedWeakReference 弱引用对象来查找内在泄漏
HeapAnalyzer 计算 KeyedWeakReference 所引用对象的最短强引用路径,来分析内存泄漏,并且构建出对象引用链出来。
内存泄漏信息送回给 DisplayLeakService,它是运行在 app 进程里的一个服务。然后在设备通知栏显示内存泄漏信息。
几个有意思的代码
如何导出 hprof 文件
File heapDumpFile = new File("heapdump.hprof");
Debug.dumpHprofData(heapDumpFile.getAbsolutePath());
如何分析 hprof 文件
这是个比较大的话题,感兴趣的可以移步另外一个开源库 ,它的祖先是 。
如何使用 HandlerThread
可以参阅 的代码,特别是关于 Handler, Loop 的使用。
怎么知道某个变量已经被 GC 回收
的 ensureGone() 函数。最主要是利用 WeakReference 和 ReferenceQueue 机制。简单地讲,就是当弱引用 WeakReference 所引用的对象被回收后,这个 WeakReference 对象就会被添加到 ReferenceQueue 队列里,我们可以通过其 poll() 方法获取到这个被回收的对象的 WeakReference 实例,进而知道需要监控的对象是否被回收了。
关于内存泄漏
内存泄漏可能很容易发现,比如 Cursor 没关闭;比如在 Activity.onResume() 里 register 了某个需要监听的事件,但在 Activity.onPause() 里忘记 unregister 了;内存泄漏也可能很难发现,比如 ,隐含地引用,并且只有在旋转屏幕时才会发生。还有更难发现,甚至无能为力的内存泄漏,比如 Android SDK 本身的 BUG 导致内存泄漏。 里就记录了一些己知的 AOSP 版本的以及其 OEM 实现版本里存在的内存泄漏。
推荐一个画图工具 ,其最大的特色是使用脚本来画图。它和
的最大区别是,前者是画图工具,类似于微软的 visio,而且支持脚本画图,后者是建模工具。是 planUML 的官方文档。它还支持一堆,比如 等。本文的就是用 planUML 画的。
编程|创业|心理学|方法论}

我要回帖

更多关于 displayleakactivity 的文章

更多推荐

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

点击添加站长微信