Android Java进程集群内存泄漏定位
前言
本篇文章讲述如何在Java进程集群中有效率的找到内存泄漏的进程,通过完成这一步,才能进行下一步进程内部代码段/对象内存泄漏的位置点。
由于产品化的Android系统中会集成数量众多的App应用集群,通过AndroidStudio DDMS逐个排查应用泄漏问题是很难的,工作效率低,而且泄漏的场景也并非常规模式能够复现。实际上更多的情况是测试使用中出现了严重的内存泄漏情况,而此时系统是离线状态下运行的,没有DDMS工作环境。为此,以下将讲述离线运行状态下,自动化定位内存泄漏进程单元。
Step 1.
首先创建自动化进程内存监控任务并在系统离线状态下运行。监控任务如下:
mkdir -p /sdcard/meminfo;f=`date "+%m_%d_%H_%M_%S"`;while [ 1 ];do date; dumpsys meminfo | busybox sed -n '1,20p'; sleep 5; done > /sdcard/meminfo/$f &
上诉监控任务会每隔5秒对系统进行内存扫描,并将其中内存使用量较大的前20名进程信息dump到本地/sdcard/meminfo/date文件下。
Step 2.
创建上述离线内存监控指令后,经过长时间的系统运行测试,可以得到系统内存进程信息文件,
Thu Oct 18 11:02:42 CST 2018
Applications Memory Usage (kB):
Uptime: 153171 Realtime: 153171
Total PSS by process:
43018 kB: system (pid 545)
32706 kB: com.****.yeqishi.launcher2 (pid 1018 / activities)
30343 kB: com.android.systemui (pid 723)
28030 kB: com.baidu.input (pid 1695)
15646 kB: com.****.settings (pid 1156)
14314 kB: com.google.android.inputmethod.latin (pid 2363)
13788 kB: zygote (pid 191)
13043 kB: com.****.yeqishi.xxx001 (pid 1865)
12826 kB: com.****.yeqishi.xxx002 (pid 1182)
12546 kB: com.****.yeqishi.xxx009 (pid 1666)
12180 kB: com.****.xxx003 (pid 951)
11422 kB: com.****.yeqishi.xxx004 (pid 930)
11081 kB: com.****.yeqishi.xxx005 (pid 2434)
10723 kB: com.****.yeqishi.xxx006 (pid 999)
10583 kB: com.****.yeqishi.xxx007 (pid 810)
10473 kB: com.****.yeqishi.xxx008 (pid 2417)
Thu Oct 18 11:02:49 CST 2018
Applications Memory Usage (kB):
Uptime: 159739 Realtime: 159739
Total PSS by process:
43178 kB: system (pid 545)
32790 kB: com.****.yeqishi.launcher2 (pid 1018 / activities)
30355 kB: com.android.systemui (pid 723)
28030 kB: com.baidu.input (pid 1695)
15646 kB: com.****.settings (pid 1156)
14302 kB: com.google.android.inputmethod.latin (pid 2363)
13788 kB: zygote (pid 191)
13043 kB: com.****.yeqishi.xxx001 (pid 1865)
12854 kB: com.****.yeqishi.xxx002 (pid 1182)
12546 kB: com.****.yeqishi.xxx009 (pid 1666)
12180 kB: com.****.xxx003 (pid 951)
...
该文件的内容会非常多,我们不需要直接去看它。
Step 3.
根据上述文件的格式,我们使用bash脚本从中分类导出各进程数据。
分类办法示例
grep "^ [6789]" ./ -r | awk '{print $4}' | xargs mkdir^
分类导出数据办法示例
for f in $(ls com*);do name=`echo $f | awk -F ":" '{print $1}'`; grep $name ./C8* | awk '{print $1}' > ${name}.csv ; done
Step 4.
根据导出的各进程内存数据csv文件,最终获得各进程的内存曲线图。
进程内存正常曲线图
进程内存泄漏曲线图
通过以上四个步骤,只要系统在离线状态下出现过内存泄漏,我们就可以找到这个进程和它出现内存泄漏时的时间与泄漏总量。下一步,我们就可以针对该进程进行进程内部代码段/对象内存泄漏点进行定位。