关于app的优化有很多方面,但是基本上都是围绕内存进行优化。今天道长主要说说内存泄露的定位,了解一下内存泄露和内存溢出的定义及区别。下面咱们开始……
一、内存泄露与内存溢出的区别
说到内存泄露,咱们首先要了解一下内存泄漏的定义。由于有些小伙伴对于内存溢出和内存泄露的区分有些迷惑。这里一块说一下。
- 内存溢出(out of memory,简称OOM)
内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,简单点说就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出出现out of memory异常。比如一个500ml的水杯,你要向水杯里倒入1000ml的水,那就是内存溢出。 - 内存泄露(memory leak)
内存泄露是指程序在申请内存后,无法释放已申请的内存空间,简单点说就是你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。分配的内存不足以放下数据项序列,称为内存溢出。比如一间书房中有10个位置适合放私房钱,道长会不定期的把私房钱拿出来或者放进去,后来有些位置道长放进去私房钱但是位置忘了,这就造成适合放私房钱的位置越来越少。最后位置满了以后道长的私房钱没地方放了,这就是溢出。从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存造成内存溢出。
所以不是所有的out of memory都是memory leak导致的,但是memory leak会最终会导致out of memory!
二、内存泄漏定位:
一般道长完成需求功能开发后再进行内存泄露的检测。之前使用Eclipse的时候都是发生OOM或做一些可能存在内存泄漏的操作后,导出HPROF文件使用MAT分析,所以分析起来比较麻烦。现在使用Studio,道长使用Lint等工具检测内存泄露就可以在内存泄露前便可以检测到可能发生内存泄露的代码。
1.Lint的使用
- 首先右击要检测的文件,点击Inspect Code
- 会有弹窗提示选择检测的范围
- 然后等待分析完成
然后根据提示处理内存泄露的代码就可以了,如果泄漏源有多处时,核心功能产生的泄漏优先处理,用户使用频繁的功能引起的泄漏优先处理。
2.LeakCanary的使用
现在道长公司的app便是集成的leakCanary。当内存泄漏发生时,LeakCanary 会弹窗提示并生成对应的堆存储信息记录,便于程序猿们直观的查看内存泄露的位置。当然LeakCanary也不是万能的。比如Android SDK中存在的一些bug便发现不了。
- 集成LeakCanary库
在gradle中的dependencies中添加如下代码:
//内存泄露
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
然后在application的onCreate()方法中添加如下代码:
//内存泄露检测
LeakCanary.install(this);
LeakCanary.install(this)执行时安装了ActivityRefWatcher来监控Activity泄漏。当 Activity.onDestroy()被调用之后,如果这个Activity没有被销毁,logcat就会打印出信息告诉你内存泄漏发生了。道长举个例子(与前文无关):例如道长在loginActivity中注册了一个Receiver,但是没有注销。运行程序logcat便会打印出信息如下:
关于内存泄露定位就到这里,这是道长检测内存泄露的大体方法,希望这篇博客能够为小伙伴提供一些帮助。当然网上还有很多检测内存泄漏和在代码中处理内存泄露的优秀方案。希望小伙伴留言告诉道长一下,先谢谢了。