最近接手的一个老项目,功能比较繁杂,是运行在安卓pos机上面的收银系统,基本需要应用整天在前台使用,对系统稳定性要求较高,不同于一般app。
今天做了内存方面的检测
首先我们用电脑连接设备,用cmd执行adb的内存检测的命令
adb shell dumpsys meminfo best.DianJiaPos
后面的best.DianJiaPos是包名,要改成自己的
执行后会显示如下信息:
这里面需要关心的有:HeapSize(堆总大小)HeapAlloc(已用大小)HeapFree(剩余可用)
分为Native Heap和Dalvik Heap,这里我们只关心Dalvik Heap
另外还有一些应用相关信息:Views,Activitys等,可以统计到已经存在的view和activity个数
那么,怎么判断一个activity是否发生泄漏?
这里有个简单的办法,先使用以上命令,获取activity个数,然后在应用内执行一些可用关闭activity的操作,比如切换用户,退出登录,或者一些界面的返回键finish等
activity执行finish或onDestroy之后,再次执行以上命令,获取内存信息,看activity个数,如果个数没有减少,这个activity就很可能发生泄漏了
下面是我的MainActivity界面
应用逻辑是,从LoginActivity中登录,登录成功进入MainActivity,然后在MainActivity中有切换用户功能,点击之后会销毁MainActivity进入LoginActivity
此时的activity数量应该是1,如果多了就很可以,可能是有其他的功能逻辑,继续持有MainActivity的引用,导致MainActivity资源无法释放
在我进行多次上述操作之后,获取内存信息,发现activity数量已经达到十几个,显然存在activity泄漏
接下来我们使用Android studio 的Analyzer Task进行分析
首先,进行可能产生内存泄漏的操作
之后,进入androidstudio开发界面,下方切换到monitors,点击下面的保存的图标
稍等片刻,androidstudio保存好hprof文件后会自动打开
打开后界面如上,右侧有一个Analyzer Task
点开它,点击蓝色箭头,会自动帮我们分析内存泄漏
如图,检测到了MainActivity
选中之后,下方会显示相关信息,这里提醒大家调试时候一定要关掉混淆,否则,这里检测出来的代码变量,都是混淆后的,很难找到目标
如上图,Analyzer Task自动帮我们检测出可能的泄漏处,并用蓝色字体显示
点开之后如图所示,这里解释一下引用关系
上图的结构,表示MainActivity被PrnDspA1088这个类的s变量引用
而s变量又被CashierFragment的dsp变量引用
那么接下来看看CashierFragment的代码
private static PrnDspA1088 dsp = null;......
dsp = new PrnDspA1088(getActivity());发现dsp是一个静态变量,而创建dsp时,又把activity传进去了,于是导致静态变量间接引用activity,activity不能释放造成内存泄漏
常见的内存泄漏原因除了static引用之外,还有资源未释放/服务未解绑/EventBus未注销/TimeTask未停止等
大家使用这些的时候一定不要忘记释放资源。