Android开发之使用Android studio结合辅助工具分析内存泄露
2016-08-07 16:17
645 查看
内存泄露,是Android开发者最头疼的事。在进入正题之前我们先从概念上来了解一下内存溢出和内存泄露有什么区别?
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出.
那么怎么才能检测内存泄露呢?网上教程非常多,不过很多都是使用Eclipse检测的, 其实1.3版本以后的Android Studio 检测内存非常方便, 如果结合上MAT工具,LeakCanary插件,一切就变得so easy了。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/09/17390f6736e465d77f2019ff3fc90921.png)
图中蓝色区域,就是程序使用的内存, 灰色区域就是空闲内存,
当然,Android内存分配机制是对每个应用程序逐步增加, 比如你程序当前使用30M内存, 系统可能会给你分配40M, 当前就有10M空闲, 如果程序使用了50M了,系统会紧接着给当前程序增加一部分,比如达到了80M, 当前你的空闲内存就是30M了。 当然,系统如果不能再给你分配额外的内存,程序自然就会OOM(内存溢出)了。 每个应用程序最高可以申请的内存和手机密切相关,比如我当前使用的华为Mate7,极限大概是200M,算比较高的了, 一般128M
就是极限了, 甚至有的手机只有可怜的16M或者32M,这样的手机相对于内存溢出的概率非常大了。
注:一般分析内存泄露, 首先运行程序,打开日志控制台,有一个标签MemZ"/kf/ware/vc/" target="_blank"
我们怎么检测内存泄露呢:首先需要明白一个概念, 内存泄露就是指,本应该回收的内存,还驻留在内存中。
一般情况下,高密度的手机,一个页面大概就会消耗20M内存,如果发现退出界面,程序内存迟迟不降低的话,可能就发生了严重的内存泄露。
我们可以反复进入该界面,然后点击dump java heap 这个按钮,然后Android Studio就开始干活了,下面的图就是正在dump
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/96fee597e234c6b320fda9f8c88e7408)
dump成功后会自动打开 hprof文件,文件以Snapshot+时间来命名
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/0010556cf37c596b6a2de33ef2949059.png)
通过Android Studio自带的界面,查看内存泄露还不是很智能,我们可以借助第三方工具,常见的工具就是MAT了,下载地址 http://eclipse.org/mat/downloads.php ,这里我们需要下载独立版的MAT. 下图是MAT一开始打开的界面, 这里需要提醒大家的是,MAT并不会准确地告诉我们哪里发生了内存泄漏,而是会提供一大堆的数据和线索,我们需要自己去分析这些数据来去判断到底是不是真的发生了内存泄漏。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/09f57ad2e6711b056d9fd1280d7b45bd.png)
接下来我们需要用MAT打开内存分析的文件, 上文给大家介绍了使用Android Studio生成了 hprof文件, 这个文件在哪呢?,在Android Studio中的Captrues这个目录中,可以找到
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/1fe40ac28d3ecaea682742c90504e9f9.png)
注意,这个文件不能直接交给MAT, MAT是不识别的, 我们需要右键点击这个文件,转换成MAT识别的。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b754bc6ed914dea379b525a31fd834e6.png)
然后用MAT打开导出的hprof(File->Open heap dump) MAT会帮我们分析内存泄露的原因
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/de8d34d4b2d018b7718b6e806dcfc265.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/9105a25691be35cc9f1c61e81aab469f.png)
项目地址:https://github.com/square/leakcanary
LeakCanary会检测应用的内存回收情况,如果发现有垃圾对象没有被回收,就会去分析当前的内存快照,也就是上边MAT用到的.hprof文件,找到对象的引用链,并显示在页面上。这款插件的好处就是,可以在手机端直接查看内存泄露的地方,可以辅助我们检测内存泄露
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/cabccd3f3e740406f0a91cc56bf7ce38.png)
使用:
在build.gradle文件中添加,不同的编译使用不同的引用:
在应用的Application onCreate方法中添加LeakCanary.install(this),如下
应用运行起来后,LeakCanary会自动去分析当前的内存状态,如果检测到泄漏会发送到通知栏,点击通知栏就可以跳转到具体的泄漏分析页面。
Tips:就目前使用的结果来看,绝大部分泄漏是由于使用单例模式hold住了Activity的引用,比如传入了context或者将Activity作为listener设置了进去,所以在使用单例模式的时候要特别注意,还有在Activity生命周期结束的时候将一些自定义监听器的Activity引用置空。
关于LeakCanary的更多分析可以看项目主页的介绍,还有这里http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
用法很简单:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b3929f110c722ea93352870184ebe799.png)
点一下是追踪, 再点一下是停止追踪, 停止追踪后 .alloc文件会自动打开,打开后界面如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b306f1048c640fe26ac7c2a3daf97261.png)
当你想查看某个方法的源码时,右键选择的方法,点击Jump to source就可以了
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/f9cc7e94fb83423d7f50cf326155eeea.png)
如果我们要观测方法执行的时间,就需要来到CPU界面
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/0f8ee536348c4a5b5dab3e7c5571381a.png)
点击Start Method Tracking, 一段时间后再点击一次, trace文件被自动打开,
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/6ad40aa370507bc7aaf5bc40c72a53ae.png)
非独占时间: 某函数占用的CPU时间,包含内部调用其它函数的CPU时间。
独占时间: 某函数占用CPU时间,但不含内部调用其它函数所占用的CPU时间。
如果方法调用次数不多,但每次调用却需要花费很长的时间的函数,可能会有问题。如果自身占用时间不长,但调用却非常频繁的函数也可能会有问题。
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
memory leak会最终会导致out of memory!
内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。
内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出.
那么怎么才能检测内存泄露呢?网上教程非常多,不过很多都是使用Eclipse检测的, 其实1.3版本以后的Android Studio 检测内存非常方便, 如果结合上MAT工具,LeakCanary插件,一切就变得so easy了。
熟悉Android Studio界面
工欲善其事,必先利其器。我们接下来先来熟悉下Android Studio的界面![](https://oscdn.geek-share.com/Uploads/Images/Content/202004/09/17390f6736e465d77f2019ff3fc90921.png)
图中蓝色区域,就是程序使用的内存, 灰色区域就是空闲内存,
当然,Android内存分配机制是对每个应用程序逐步增加, 比如你程序当前使用30M内存, 系统可能会给你分配40M, 当前就有10M空闲, 如果程序使用了50M了,系统会紧接着给当前程序增加一部分,比如达到了80M, 当前你的空闲内存就是30M了。 当然,系统如果不能再给你分配额外的内存,程序自然就会OOM(内存溢出)了。 每个应用程序最高可以申请的内存和手机密切相关,比如我当前使用的华为Mate7,极限大概是200M,算比较高的了, 一般128M
就是极限了, 甚至有的手机只有可怜的16M或者32M,这样的手机相对于内存溢出的概率非常大了。
注:一般分析内存泄露, 首先运行程序,打开日志控制台,有一个标签MemZ"/kf/ware/vc/" target="_blank"
我们怎么检测内存泄露呢:首先需要明白一个概念, 内存泄露就是指,本应该回收的内存,还驻留在内存中。
一般情况下,高密度的手机,一个页面大概就会消耗20M内存,如果发现退出界面,程序内存迟迟不降低的话,可能就发生了严重的内存泄露。
我们可以反复进入该界面,然后点击dump java heap 这个按钮,然后Android Studio就开始干活了,下面的图就是正在dump
dump成功后会自动打开 hprof文件,文件以Snapshot+时间来命名
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/0010556cf37c596b6a2de33ef2949059.png)
通过Android Studio自带的界面,查看内存泄露还不是很智能,我们可以借助第三方工具,常见的工具就是MAT了,下载地址 http://eclipse.org/mat/downloads.php ,这里我们需要下载独立版的MAT. 下图是MAT一开始打开的界面, 这里需要提醒大家的是,MAT并不会准确地告诉我们哪里发生了内存泄漏,而是会提供一大堆的数据和线索,我们需要自己去分析这些数据来去判断到底是不是真的发生了内存泄漏。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/09f57ad2e6711b056d9fd1280d7b45bd.png)
接下来我们需要用MAT打开内存分析的文件, 上文给大家介绍了使用Android Studio生成了 hprof文件, 这个文件在哪呢?,在Android Studio中的Captrues这个目录中,可以找到
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/1fe40ac28d3ecaea682742c90504e9f9.png)
注意,这个文件不能直接交给MAT, MAT是不识别的, 我们需要右键点击这个文件,转换成MAT识别的。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b754bc6ed914dea379b525a31fd834e6.png)
然后用MAT打开导出的hprof(File->Open heap dump) MAT会帮我们分析内存泄露的原因
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/de8d34d4b2d018b7718b6e806dcfc265.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/9105a25691be35cc9f1c61e81aab469f.png)
LeakCanary
上面介绍了MAT检测内存泄露, 再给大家介绍LeakCanary。项目地址:https://github.com/square/leakcanary
LeakCanary会检测应用的内存回收情况,如果发现有垃圾对象没有被回收,就会去分析当前的内存快照,也就是上边MAT用到的.hprof文件,找到对象的引用链,并显示在页面上。这款插件的好处就是,可以在手机端直接查看内存泄露的地方,可以辅助我们检测内存泄露
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/cabccd3f3e740406f0a91cc56bf7ce38.png)
使用:
在build.gradle文件中添加,不同的编译使用不同的引用:
dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3' }[/code]
在应用的Application onCreate方法中添加LeakCanary.install(this),如下
public class ExampleApplication extends Application @Override public void onCreate() { super.onCreate(); LeakCanary.install(this); } }[/code]
应用运行起来后,LeakCanary会自动去分析当前的内存状态,如果检测到泄漏会发送到通知栏,点击通知栏就可以跳转到具体的泄漏分析页面。
Tips:就目前使用的结果来看,绝大部分泄漏是由于使用单例模式hold住了Activity的引用,比如传入了context或者将Activity作为listener设置了进去,所以在使用单例模式的时候要特别注意,还有在Activity生命周期结束的时候将一些自定义监听器的Activity引用置空。
关于LeakCanary的更多分析可以看项目主页的介绍,还有这里http://www.liaohuqiu.net/cn/posts/leak-canary-read-me/
追踪内存分配
如果我们想了解内存分配更详细的情况,可以使用Allocation Traker来查看内存到底被什么占用了。用法很简单:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b3929f110c722ea93352870184ebe799.png)
点一下是追踪, 再点一下是停止追踪, 停止追踪后 .alloc文件会自动打开,打开后界面如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/b306f1048c640fe26ac7c2a3daf97261.png)
当你想查看某个方法的源码时,右键选择的方法,点击Jump to source就可以了
查询方法执行的时间
Android Studio 功能越来越强大了, 我们可以借助AS观测各种性能,如下图:![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/f9cc7e94fb83423d7f50cf326155eeea.png)
如果我们要观测方法执行的时间,就需要来到CPU界面
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/0f8ee536348c4a5b5dab3e7c5571381a.png)
点击Start Method Tracking, 一段时间后再点击一次, trace文件被自动打开,
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/11/6ad40aa370507bc7aaf5bc40c72a53ae.png)
非独占时间: 某函数占用的CPU时间,包含内部调用其它函数的CPU时间。
独占时间: 某函数占用CPU时间,但不含内部调用其它函数所占用的CPU时间。
我们如何判断可能有问题的方法?
通过方法的调用次数和独占时间来查看,通常判断方法是:如果方法调用次数不多,但每次调用却需要花费很长的时间的函数,可能会有问题。如果自身占用时间不长,但调用却非常频繁的函数也可能会有问题。
综述
上面给大家介绍了若干使用Android Studio检查程序性能的工具,工具永远是辅助,不要因为工具耽误太长时间。如果有问题,欢迎大家纠正。相关文章推荐
- Android 内存泄露原因及使用MAT工具分析
- Android_使用Android studio分析内存泄露
- Android studio内存泄露分析工具使用
- Android 内存泄露原因及使用MAT工具分析
- [Android内存分析] 使用MAT工具做内存泄露分析一
- Android中使用Handler造成内存泄露的分析和解决
- android 内存分析(MAT工具的使用)
- [Android Memory] 内存分析工具 MAT 的使用
- Android内存分析工具DDMS heap + MAT 安装和使用
- Android 性能优化之使用MAT分析内存泄露问题
- Android 性能优化之使用MAT分析内存泄露问题
- android开发内存泄露分析
- android 内存分析(MAT工具的使用)
- Android 性能优化之使用MAT分析内存泄露问题
- Android 中使用内存监测工具Heap,及内存分析工具 MAT
- Android中使用Handler造成内存泄露的分析和解决
- Android内存分析工具DDMS heap + MAT 安装和使用
- Android内存分析工具DDMS heap + MAT 安装和使用
- Android中使用Handler造成内存泄露的分析和解决
- 内存泄露分析之MAT工具简单使用