前言
上周有一个任务就是要我分析内存中重复的Bitmap的问题的,就是这个Android CMake错误解决的续集。
忙于其他的问题和五一放假,现在才有时间重新看看这个问题是否可以用Matrix解决!╮(╯▽╰)╭
这个问题貌似有点难搞(在不考虑Hook Bitmap接口),不过幸好微信的老哥开源了一个微信的APM工具,里面包含了当Activity销毁的时候发生内存泄漏dump内存中的数据的matrix-resource-canary
。这个模块是Resource Canary
下的,这一部分的功能仅仅是通过系统的Debug类提供的接口将内存中的数据dump到Hprof文件中,然后再通过matrix-resource-canary
读取该Hprof文件,分析其中的一些StringId、BitmapId,找到Bitmap的Buffer,找出不需要的数据部分并裁剪,保留String和Bitmap等的对象数据。
这个matrix-resource-canary
的模块的触发时机比较傲娇——bitmap问题的分析目前必须依赖activity泄漏检测得到的产物。
如果仅仅需要分析Bitmap的问题,需要我们自己去修改检测的逻辑,这个部分还是比较麻烦的,需要理解matrix-resource-canary
的原理才可以做出修改和定制。
分析
不多说,先上我分析的图(不严格按照流程图以及类图来画):
ResourcePlugin
ResourcePlugin
是该模块的入口,负责注册Android生命周期的监听以及配置部分参数和接口回调。
ActivityRefWatcher
ResourcePlugin
中负责Android生命周期监听的其实是ActivityRefWatcher
。
ActivityRefWatcher
负责的任务其实蛮多的,其中的几个比较重要的功能类都在ActivityRefWatcher
中实例化并完成Android Activity内存泄漏时,弹出Dump内存的Dialog、Dump内存数据、读取内存数据裁剪Hprof文件、生成包含裁剪后的Hprof以及泄漏的Activity的信息(进程号、Activity名、时间等)、通知主线程完成内存信息的备份并关闭Dialog。
RetryableTaskExecutor
RetryableTaskExecutor
中包含了两个Handler对象,一个mBackgroundHandler
和mMainHandler
,分别给主线程和后台的线程提交任务。默认重试次数是3。
DumpStorageManager
DumpStorageManager
这个类功能很简单,其实就是准备Hprof所在的文件夹和创建Hprof文件,方便写入数据到文件中。
AndroidHeapDumper
AndroidHeapDumper
这个其实就是封装了android.os.Debug
的接口的类。
主要是用系统提供的类android.os.Debug
Dump内存信息到本地,android.os.Debug
会在本地生成一个Hprof文件,也是Matrix需要分析和裁剪的原始文件。
- 问什么要裁剪?
- 原始的Hprof文件动不动就几百兆,如果不裁剪、压缩,文件太大了。
- 流程化,可以通过Matrix提供的工具直接还原内存泄漏的的Bitmap原图,并提供泄漏的引用链。
一般Dump一次要5s~15s之间,所以不能做成线上的。
Dump的时候,AndroidHeapDumper
会展示一个Dialog提示当前正在Dump中,Dump完毕就会将Dialog关闭。
AndroidHeapDumper.HeapDumpHandler
这个是裁剪Hprof操作的核心部分了,所有的核心逻辑都在这里面。
让我们先看看AndroidHeapDumper.HeapDumpHandler
的实例化过程吧。
public static class ComponentFactory {
protected RetryableTaskExecutor createDetectExecutor(ResourceConfig config, HandlerThread handlerThread) {
return new RetryableTaskExecutor(config.getScanIntervalMillis(), handlerThread);
}
protected DumpStorageManager createDumpStorageManager(Context context) {
return new DumpStorageManager(context);
}
protected AndroidHeapDumper createHeapDumper(Context context, DumpStorageManager dumpStorageManager) {
return new AndroidHeapDumper(context, dumpStorageManager);
}
// 创建一个按照队列顺序执行任务的Service
protected AndroidHeapDumper.HeapDumpHandler createHeapDumpHandler(final Context context, ResourceConfig resourceConfig) {
return new AndroidHeapDumper.HeapDumpHandler() {
@Override
public void process(HeapDump result) {
CanaryWorkerService.shrinkHprofAndReport(context, result);
}
};
}
}
AndroidHeapDumper.HeapDumpHandler
负责将本地的Hprof文件的信息类HeapDump
交由CanaryWorkerService
去执行裁剪的操作。
CanaryWorkerService
继承自MatrixJobIntentService,MatrixJobIntentService继承自Service。
找出Activity泄漏的引用链、Bitmap、裁剪Hprof文件,之后将引用链、进程号、时间、Activity名称等写入文件result.info
中,并和裁剪后的Hprof文件一起压缩到zip格式的压缩包中。
从CanaryWorkerService.doShrinkHprofAndReport
中可以找到new HprofBufferShrinker().shrink(hprofFile, shrinkedHProfFile);
,这是一个封装了裁剪逻辑的组合类。
让我们看看实现:
public void shrink(File hprofIn, File hprofOut) throws IOException {
...
// 使用了访问者模式
final HprofReader reader = new HprofReader(new BufferedInputStream(is));
reader.accept(new HprofInfoCollectVisitor());
// Reset.
is.getChannel().position(0);
reader.accept(new HprofKeptBufferCollectVisitor());
// Reset.
is.getChannel().position(0);
reader.accept(new HprofBufferShrinkVisitor(new HprofWriter(os)));
...
}
访问者 | 说明 |
---|---|
HprofInfoCollectVisitor | 收集一些必备的StringId、ClassId、BufferId以及String实例和Bmp实例。 |
HprofKeptBufferCollectVisitor | 收集需要保留的16进制的地址。 |
HprofBufferShrinkVisitor | 去掉不需要保留的二进制数据【裁剪】。 |
HprofInfoCollectVisitor
、HprofKeptBufferCollectVisitor
、HprofBufferShrinkVisitor
均继承自HprofVisitor
,由HprofReader
代理访问不同Visitor
能力。
CanaryResultService
继承自MatrixJobIntentService,MatrixJobIntentService继承自Service。
负责通知主线程Dump、裁剪、压缩数据完毕。
更多
- 更多细致的原理请看看Matrix ResourceCanary – Activity 泄漏及Bitmap冗余检测,这里很详细的解析了。
其实还有很多的东西可以写的,比如如何分析Hprof文件,这个有时间再仔细研究下看看。
这里其实就分析了matrix-resource-canary-android
的部分,还有解析裁剪后的Hprof文件的命令行库matrix-resource-canary-analyzer
没有分析。
CLIMain
这个命令行工具需要使用gradlew buildResourceCheckJar
编译得到。位于matrix/matrix/matrix-android/matrix-resource-canary/matrix-resource-canary-analyzer/build/libs
下的matrix-resource-canary-analyzer-0.5.1.jar
。
- matrix-resource-canary
- matrix-resource-canary-android
- matrix-resource-canary-analyzer
- matrix-resource-canary-common
这里面很多有意思的知识点可以挖挖看看!O(∩_∩)O