Android Java进程memleak自动化检测与堆转储方法

前言

由于前一篇文章讲了如何在Java应用集群中高效找出内存泄漏进程的方法,现在开始分享Java进程memleak自动化检测与堆转储方法。

在Java进程集群中,某一个或几个Java进程内存泄漏场景经常是很隐蔽的,这可能需要一系列的进程间业务动作才能暴露出来。同样,在某一个存在内存泄漏的Java进程内部,如果直接研究代码是否存在内存泄漏,这对理论基础和实际经验要求很高,而在高强度的实际场景测试下却是可以有效的复现内存泄漏的。针对上面两个内存泄漏检测方面的困难问题,上一篇文章已经讲了第一个问题的解决办法,现在可以将第二个问题的解决办法。

 

目录

测试条件

监控进程设置

关闭系统Selinux

测试方法

内存监控捕获办法

测试命令

命令说明

数据查看与抽取

查看机器测试文件

Hprof文件分析

hprof格式转化

hprof数据分析

定位泄漏原因


 

测试条件

  • 监控进程设置

要对监控进程执行堆转储操作,需要在应用源码开启debuggable开关。

+++ b/app/build.gradle
@@ -15,6 +15,7 @@ android {
         release {
             minifyEnabled false
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            debuggable true
         }

 

  • 关闭系统Selinux

因权限问题,dumphead操作需要关闭selinux,关闭命令为

setenforce 0

 

测试方法

通过设置随机种子值进行monkey测试,测试命令样本如下:

monkey -s 123456 --throttle 500 --ignore-crashes --ignore-timeouts --monitor-native-crashes -v -v -v 5000000 & 

 

内存监控捕获办法

  • 监控方式

为了监控发现内存泄漏点,我们需要获取的重要信息是发生内存泄漏时,内存泄漏之前的内存快照和内存泄漏之后的内存快照,通过这两份内存快照我们即可定位内存泄漏点。如下示意图所示:

通过对内存泄漏捕获时机确认的建模,可以知道红色曲线表示内存总量上升量超过阈值,此时需要进行内存快照,而当绿色曲线表示内存总量下降量超过阈值时,此时也需要进行内存快照。

 

  • 测试命令

Process=com.csdn.yeqishi.memleak; lastsize=0; threshod=10000;n=1; while [ $n -lt 300 ];do bigdump=0;smalldump=0; eval $(dumpsys meminfo $Process | grep TOTAL | busybox awk '{printf ("m=%s",$2)}'); if [ $m -gt $lastsize+$threshod ]; then bigdump=1; fi; if [ $m+$threshod -lt $lastsize ];then smalldump=1; fi; date; echo "mem=$m lastsize=$lastsize big=$bigdump small=$smalldump n=$n"; if [ $bigdump == 1 ] || [ $smalldump == 1 ];then am dumpheap $Process /sdcard/dpmi_launcher_$n.hprof; lastsize=$m; ((n=n+1)); fi; sleep 10; done > /sdcard/dpmi-info1 &

Process=com.csdn.yeqishi.memleak; lastsize=0; threshod=10000;n=1; while [  $n -lt 300  ];do bigdump=0;smalldump=0; eval $(dumpsys meminfo $Process | grep TOTAL | busybox awk '{printf  ("m=%s",$2)}'); if [ $m -gt $lastsize+$threshod ]; then bigdump=1; fi; if [ $m+$threshod -lt $lastsize ];then smalldump=1; fi; date; echo "mem=$m lastsize=$lastsize big=$bigdump small=$smalldump n=$n";  if [ $bigdump == 1 ] || [ $smalldump == 1 ];then  am dumpheap $Process  /sdcard/dpmi_launcher_$n.hprof; lastsize=$m; ((n=n+1)); fi;  sleep 10; done > /sdcard/dpmi-info1 &
  • 命令说明

Process:指定监控的进程名称

lastsize:最近一次检测到的满足阈值触发条件时的进程堆大小

threshod:阈值大小,(当进程堆内存变化超过阈值时会进行堆转储操作)

上诉命令会每隔10s查询一次监控进程的堆大小,当堆大小与lastsize相比变化超过threshod的值时,触发执行对监控进程的堆转储操作。(由于堆转储生成的文件较大,30M+,所以总监控次数控制在300)

 

数据查看与抽取

  • 查看机器测试文件

自动化堆转储操作命令会将测试过程信息输出到/sdcard/dpmi开头的文件中,通过查看文件可以知道触发动作次数。如下:

通过打印dpmi-info1文件,可以知道测试过程数据,如进程堆内存使用和触发动作次数。

当怀疑监控进程堆内存发生泄漏时,可以导出/sdcard/dpmi-info1文件,执行以下命令导出监控进程堆内存历史数据到表格文件中,同时利用表格软件生成数据曲线,确认内存泄漏或者内存使用情况。

cat C8W7KPSQB3.dpmi-info1 | grep mem | awk -F "[= ]" '{print $2}' > C8W7KPSQB3.csv

通过以下命令确认内存变化超过阈值时触发动作的发生时间

cat C8W7KPSQB3.dpmi-info1 | tr "\n" ","  | sed 's#Mon #\nMon #g' |sed 's#Tue #\nTue #g' | grep =1 > a

根据时间或者动作次数确认堆转储hprof 文件,上诉信息可选择第三、四次触发动作时的hprof文件。

 

Hprof文件分析

  • hprof格式转化

命令导出的gprof文件需要格式转换,转换工具为sdk/platform-tools/hprof-conv

  • hprof数据分析

MAT分析办法参考:https://blog.csdn.net/tabactivity/article/details/73773916

  • 定位泄漏原因

上诉对比图可以看出第三、四次堆转储触发时进程对象变化对比,个人建议从自己可知的大对象(与根对象引用深度浅的目标对象)确认代码泄漏点。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值