LeakC anary傻瓜式的内存泄露检测工具
在Andr oid开发过程中如果需要处理图片或者大量数据的时候常常会遇到OOM(java. lang.OutOf Memor yErro r),一般出现最多的是在创建Bitm ap上也有可能是在内存中处理了大量的数据造成。
一般会针对Bitam p做下面几种的优化:
1.增加进程的内存
2.使用Bit map.Confi g.ALPHA_8(图片失真)
3.显示的调用Syste m.gc()
4. catch Excep tion
5.调用bit map.recyc le()
6.缩小bitmap的大小(如果是读取的原图是一个大图应该先采用这种方式 Bitma p如果是刚好适配屏幕的就不需要缩小了)
7.使用弱引用和软引用(googl e已经不建议使用了,Andro id的GC效率非常高只要保证对象没有被引用即可)
但是我们会忽略掉一个问题就是什么造成了OOM?一般都发生OOM崩溃的地方都不一定是内存泄露的地方崩溃了的原因可能Ac tivit y造成的内存泄露也可能是操作数据库造成的内存泄露 当内存已经非常接近峰值的时候这个时候恰巧要创建一个Bitm ap对象就会发生OO M(Bitma p对象占用的内存空间比较大) 。
内存泄露
每个对象都有自己的生命周期Activ ity会调用onDe stroy做销毁处理但是如果使用Acti vity的Conte xt调用T oast,就会把这个Activ ity的引用传给了T oast,而Toas t的生命周期不会随着Activ ity的销毁而销毁,这样就造成了Acti vity的内存泄露 因为它被T oast引用着。
常见的内存泄露形成的原因:
1. Toast持有Act ivity的引用
2.数据库游标Curso r没有关闭
3. Adapt er没有复用conv ertVi ew
4.对象被生命周期更长的对象引用 Activ ity被静态集合引用
. . . .
监控内存的方式
Heap Dump是一种Jav a比较常用的检测内存的方式简单来说就是我们在一个初始状态A Dump一次内存在做了一些操作之后回到状态A再Dump一次内存。
对两次Du np的内存数据(hprof )使用分析工具做分析(MAT) ,根据分析的结果就能知道是否存在内存泄露这种方式比较复杂和繁琐并不是特别易用。
Moito rs:Andro idSDK 自带的内存监控工具Monit ors能看到内存的变化内存是增加还是减少.打开一个A ctivi ty会导致内存增加关闭一个A ctivi ty会导致内存减少反复的实验如果每次打开一个Ac tivit y再关闭之后增加的内存不会减少就说明这个Activ ity有内存泄露的问题可以使用l og辅助进行检测这种方式的缺点是并不是特别的准确 因为内存的释放和对象的生命周期有关也和GC的调用有关。
而Leak Canar y就是一个简单的方便的内存检测工具可以轻易的发现内存问题还会生成更加简单清晰的报告。
LeakC anary
LeakC anary是一个开源的检测内存泄露的ja va库。项目地址 https
://githu b.com/squar e/leakc anary
LeakC anary实际上就是在本机上自动做了He ap dump对生成的h prof文件进行分析展示结果。和手工分析Heap Dump的方式得到的结果是一样的。
下面是一个LeakC anary的结果截图
集成Lea kCana ry
在buil d.gradl e添加依赖depen denci es {debug Compi le 'com. squar eup. leakc anary :leakc anary -andro id:1.3. 1'relea seCom pile 'com. squar eup. leakc anary :leakc anary -andro id-no-op: 1.3. 1'testC ompil e 'com. squar eup. leakc anary :leakc anary -andro id-no-op: 1.3. 1'
}
使用Lea kCana ry会影响程序的性能尤其是在H eap dump和分析操作时不过我们可以在依赖里面指定对应的版本debug的时候才进行分析relea se的时候不进行分析。debug Compi le可以使用检测版本 com. squar eup. leakc anary :leakc anary -andro id relea seCom pile使用no-op模式 即No Opera tion Perfo rmed就是不会把对应的类库编译,指定类库为无用的指令:com. squar eup. leakc anary :leakc anary -andro id-no-op设置L eakCa nary为无用指令。
然后在Ap plica tion中加入分析A ctivi ty的代码
publi c class Examp leApp licat ion exten ds Appli catio n{
@Overr ide publi cvoid onCre ate() {super .onCre ate() ;
LeakC anary .insta ll(this) ;
}
}
这样就可以检测Act ivity的内存泄露了。 内部实现使用了Act ivity Lifec ycleC allba cks方法监控所有A ctivi ty的生命周期。
检测其他对象
LeakC anary中提供了R efWat cher类可, 以用来监控所有的对象。
首先需要实例化Ref Watch er:publi c stati c RefWa tcher sRefW atche r=LeakC anary .insta ll(mCont ext) ;
对于监控的对象使用sRefW atche r.watch (this)
一般我们是在对象销毁的时候对对象进行监控,比如内部实现的对于A ctivi ty的监控:priva tefinal Activ ityLi fecyc leCal lback slifec ycleC allba cks=newActiv ityLi fecyc leCal lback s() {publi c void onAct ivity Creat ed(Activ ity activ ity, Bundl esaved Insta nceSt ate) {
}publi cvoid onAct ivity Start ed(Activ ity activ ity) {
}
publi cvoid onAct ivity Resum ed(Activ ity activ ity) {
}publi cvoid onAct ivity Pause d(Activ ity activ ity) {
}publi cvoid onAct ivity Stopp ed(Activ ity activ ity) {
}publi c void onAct ivity SaveI nstan ceSta te(Activ ity activ ity,Bundl e outSt ate) {
}publi cvoid onAct ivity Destr oyed(Activ ity activ ity) {
Activ ityRe fWatc her. this.onAct ivity Destr oyed(activ ity) ;
}
} ;
只是在on Activ ityDe stroy ed的时候才对于ac tivit y进行了监控。
如何解决内存泄露
一般情况内存泄露的原因都是由于引用的使用不当造成的而且And roid的
GC能够保证回收循环引用(如果一个循环引用没有外部引用时就会被回收)而且And roid的GC效率很高当然GC的算法本身也在不停的改进。
一般情况下我们尽量避免错误的引用方式带来的内存泄露问题
1.生命周期长的对象引用生命周期短的对象 比如sta tic的对象群引用A ctivi ty
2.使用App licat ion的C ontex t对象而不是Ac tivit y的Con text
3.避免非静态类的内部类对于类的隐式引用使用静态的内部类
4.使用And roid的缓存机制 比如Lis tView的复用机制
5.手动关闭资源比如Cur ous的关闭
6. regis terRe ceive r和unR egist erRec eiver成对出现
SoftShellWeb是一家2019年成立的国外主机商,商家在英格兰注册,提供的产品包括虚拟主机和VPS,其中VPS基于KVM架构,采用SSD硬盘,提供IPv4+IPv6,可选美国(圣何塞)、荷兰(阿姆斯特丹)和台湾(台北)等机房。商家近期推出台湾和荷兰年付特价VPS主机,其中台湾VPS最低年付49美元,荷兰VPS年付24美元起。台湾VPSCPU:1core内存:2GB硬盘:20GB SSD流量...
HostKvm也发布了开年促销方案,针对香港国际和美国洛杉矶两个机房的VPS主机提供7折优惠码,其他机房业务提供8折优惠码。商家成立于2013年,提供基于KVM架构的VPS主机,可选数据中心包括日本、新加坡、韩国、美国、中国香港等多个地区机房,均为国内直连或优化线路,延迟较低,适合建站或者远程办公等。下面列出几款主机配置信息。美国洛杉矶套餐:美国 US-Plan1CPU:1core内存:2GB硬盘...
如果我们较早关注NameCheap商家的朋友应该记得前几年商家黑色星期五和网络星期一的时候大促采用的闪购活动,每一个小时轮番变化一次促销活动而且限量的。那时候会导致拥挤官网打不开迟缓的问题。从去年开始,包括今年,NameCheap商家比较直接的告诉你黑色星期五和网络星期一为期6天的活动。没有给你限量的活动,只有限时六天,这个是到11月29日。如果我们有需要新注册、转入域名的可以参加,优惠力度还是比...