Android 关于内存泄漏的一些总结

(做Android开发一年多后,第一次发文章,还都是拷过来的,主要是方便下次看)


避免Context相关的内存泄露的两种方法

  • 最明显的方法是避免在Context的作用域之外使用它。
  • 第二种方法就是使用Application Context。这个Context会一直存活只要你的应用是活着的,并且不依赖于Activity的生命周期。如果你打算维持一个长时间存在的并且需要Context的对象时,记住使用应用的Context。获取方法:Context.getApplicationContext()或Activity.getApplication()

同时,为了避免Context相关的内存泄露,记住下面几点:

  • 不要维持一个长时间存在对Activity的Context的引用(Activity的引用和Activity有着一样的生命周期)
  • 使用Application的Context而不是Activity的Context
  • 避免在Activity中使用非静态内部类,如果你不想控制他们的生命周期。使用静态内部类,并在它的内部创建一个对Activity的弱引用

参考:http://www.cnblogs.com/JohnTsai/p/5256295.html


1、对于生命周期比Activity长的对象如果需要应该使用ApplicationContext
2、在涉及到Context时先考虑ApplicationContext,当然它并不是万能的,对于有些地方则必须使用Activity的Context

3、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏
4、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
将内部类改为静态内部类 静态内部类中使用弱引用来引用外部类的成员变量

5、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null
6、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性

Android 关于内存泄漏的一些总结

集合等的生命周期

参考:http://blog.csdn.net/sinat_22949049/article/details/51925411


使用新版Android Studio检测内存泄露和性能

内存泄露,是Android开发者最头疼的事。可能一处小小的内存泄露,都可能是毁于千里之堤的蚁穴。 

怎么才能检测内存泄露呢?网上教程非常多,不过很多都是使用Eclipse检测的, 其实1.3版本以后的Android Studio 检测内存非常方便, 如果结合上MAT工具,LeakCanary插件,一切就变得so easy了。

熟悉Android Studio界面

工欲善其事,必先利其器。我们接下来先来熟悉下Android Studio的界面 

一般分析内存泄露, 首先运行程序,打开日志控制台,有一个标签MemZ喎�"/kf/ware/vc/" target="_blank" class="keylink">vcnkgLM7Sw8e/ydLU1NrV4rj2vefD5rfWzva1scews8zQ8sq508O1xMTatObH6b/2LCDSu8S/wcvIuywgztLDx9TZ0rKyu9Do0qq/4L/gtcTU2mxvZ2NhdNbQ0bDV0sTatOa1xMjV1r7By6GjPC9wPgoKPHA+PHN0cm9uZz7NvNbQwLbJq8f40/KjrL7NysezzNDyyrnTw7XExNq05qOsILvSyavH+NPyvs3Kx7/Vz9DE2rTmo6w8L3N0cm9uZz4gPGJyPgq1sci7o6xBbmRyb2lkxNq05rfWxeS7+tbGyse21MO/uPbTptPDs8zQ8tbwsr3U9rzTLCCxyMjnxOOzzNDytbHHsMq508MzME3E2rTmLCDPtc2zv8nE3LvhuPjE47fWxeQ0ME0sILWxx7C+zdPQMTBNv9XP0CwgyOe5+7PM0PLKudPDwcs1ME3ByyzPtc2zu+G99L3T18W4+LWxx7CzzNDy1Pa809K7sr+31iyxyMjntO+1vcHLODBNo6wgILWxx7DE47XEv9XP0MTatOa+zcrHMzBNwcuhoyAgtbHIuyzPtc2zyOe5+7K7xNzU2bj4xOO31sXktu7N4rXExNq05iyzzNDy19TIu77Nu+FPT00oxNq05tLns/YpwcuhoyDDv7j206bTw7PM0PLX7rjfv8nS1Mnqx+u1xMTatOa6zcrWu/rD3MfQz+C52KOsscjI587StbHHsMq508O1xLuqzqpNYXRlNyy8q8/etPO4xcrHMjAwTSzL47HIvc+437XEwcssICDSu7DjMTI4TSC+zcrHvKvP3sHLLCDJ9dbB09C1xMrWu/rWu9PQv8nBr7XEMTZNu/LV3zMyTaOs1eLR+bXEyta7+s/gttTT2sTatObS57P2tcS4xcLKt8ezo7TzwcuhozwvcD4KCgoKPGgyIGlkPQ=="我们怎么检测内存泄露呢">我们怎么检测内存泄露呢

首先需要明白一个概念, 内存泄露就是指,本应该回收的内存,还驻留在内存中。 

一般情况下,高密度的手机,一个页面大概就会消耗20M内存,如果发现退出界面,程序内存迟迟不降低的话,可能就发生了严重的内存泄露。 
我们可以反复进入该界面,然后点击dump java heap 这个按钮,然后Android Studio就开始干活了,下面的图就是正在dump 
Android 关于内存泄漏的一些总结

dump成功后会自动打开 hprof文件,文件以Snapshot+时间来命名 
Android 关于内存泄漏的一些总结

通过Android Studio自带的界面,查看内存泄露还不是很智能,我们可以借助第三方工具,常见的工具就是MAT了,下载地址 http://eclipse.org/mat/downloads.php ,这里我们需要下载独立版的MAT. 下图是MAT一开始打开的界面, 这里需要提醒大家的是,MAT并不会准确地告诉我们哪里发生了内存泄漏,而是会提供一大堆的数据和线索,我们需要自己去分析这些数据来去判断到底是不是真的发生了内存泄漏。

Android 关于内存泄漏的一些总结

接下来我们需要用MAT打开内存分析的文件, 上文给大家介绍了使用Android Studio生成了 hprof文件, 这个文件在呢, 在Android Studio中的Captrues这个目录中,可以找到 
Android 关于内存泄漏的一些总结

注意,这个文件不能直接交给MAT, MAT是不识别的, 我们需要右键点击这个文件,转换成MAT识别的。 
Android 关于内存泄漏的一些总结

然后用MAT打开导出的hprof(File->Open heap dump) MAT会帮我们分析内存泄露的原因 
Android 关于内存泄漏的一些总结
Android 关于内存泄漏的一些总结

LeakCanary

上面介绍了MAT检测内存泄露, 再给大家介绍LeakCanary。 
项目地址:https://github.com/square/leakcanary

LeakCanary会检测应用的内存回收情况,如果发现有垃圾对象没有被回收,就会去分析当前的内存快照,也就是上边MAT用到的.hprof文件,找到对象的引用链,并显示在页面上。这款插件的好处就是,可以在手机端直接查看内存泄露的地方,可以辅助我们检测内存泄露 
Android 关于内存泄漏的一些总结

使用: 
在build.gradle文件中添加,不同的编译使用不同的引用:

1
2
3
4
<codeclass=" hljs matlab">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),如下

1
2
3
4
5
6
7
<codeclass=" hljs java">publicclass ExampleApplication extendsApplication
    @Override
    publicvoid 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来查看内存到底被什么占用了。 
用法很简单: 
Android 关于内存泄漏的一些总结

点一下是追踪, 再点一下是停止追踪, 停止追踪后 .alloc文件会自动打开,打开后界面如下: 
Android 关于内存泄漏的一些总结
当你想查看某个方法的源码时,右键选择的方法,点击Jump to source就可以了

查询方法执行的时间

Android Studio 功能越来越强大了, 我们可以借助AS观测各种性能,如下图: 
Android 关于内存泄漏的一些总结

如果我们要观测方法执行的时间,就需要来到CPU界面 
Android 关于内存泄漏的一些总结

点击Start Method Tracking, 一段时间后再点击一次, trace文件被自动打开, 
Android 关于内存泄漏的一些总结

非独占时间: 某函数占用的CPU时间,包含内部调用其它函数的CPU时间。 
独占时间: 某函数占用CPU时间,但不含内部调用其它函数所占用的CPU时间。

我们如何判断可能有问题的方法?

通过方法的调用次数和独占时间来查看,通常判断方法是:

如果方法调用次数不多,但每次调用却需要花费很长的时间的函数,可能会有问题。 如果自身占用时间不长,但调用却非常频繁的函数也可能会有问题。

综述

上面给大家介绍了若干使用Android Studio检查程序性能的工具,工具永远是辅助,不要因为工具耽误太长时间。如果有问题,欢迎大家纠正。

参见:http://www.2cto.com/kf/201512/455421.html