基于Android Studio的内存泄漏检测与解决

本文介绍如何使用Android Studio内置工具检测和分析应用内存泄漏问题,通过具体案例展示内存泄漏原因及解决方案。

http://wetest.qq.com/lab/view/99.html



自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclipse,成为主流的Android开发IDE。Android Studio在为我们提供了良好的编码体验的同时,也提供了许多对App性能分析的工具,让开发者可以更方便分析App性能。Google在IO大会上一直告诫开发者不要无节制的使用手机内存,要注意一些不良的开发习惯会导致App的内存泄漏。虽然如今网上检测App内存泄漏的文章汗牛充栋,但是要使用DDMS和MAT,不仅使用步骤复杂繁琐,而且要手动排查内存泄漏的位置,操作起来多有不便。其实Android Studio已经开始支持自动进行内存泄漏检查了,本文就带着大家一探其中的奥妙吧。


什么是内存泄漏
Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC的对象没有被回收掉。


举个栗子

    private static Leak mLeak;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        mLeak = new Leak();
    }

    class Leak {
    }

mLeak是存储在静态区的静态变量,而Leak是内部类,其持有外部类Activity的引用。这样就导致Activity需要被销毁时,由于被mLeak所持有,所以系统不会对其进行GC,这样就造成了内存泄漏。


再举一个最常犯的栗子

public class Singleton {
    private static Singleton instance;
    private Context mContext;
    private Singleton(Context context){
        this.mContext = context;
    }

    public static Singleton getInstance(Context context){
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton(context);
                }
            }
        }
        return instance;
    }
}

如果我们在在调用Singleton的getInstance()方法时传入了Activity。那么当instance没有释放时,这个Activity会一直存在。因此造成内存泄露。
解决方法可以将new Singleton(context)改为new Singleton(context.getApplicationContext())即可,这样便和传入的Activity没关系了。


内存泄漏的检测
打开Android Studio,编译代码,在模拟器或者真机上运行App,然后点击,在Android Monitor下点击Monitor对应的Tab,进入如下界面


在Memory一栏中,可以观察不同时间App内存的动态使用情况,点击可以手动触发GC,点击可以进入HPROF Viewer界面,查看Java的Heap,如下图

Reference Tree代表指向该实例的引用,可以从这里面查看内存泄漏的原因,Shallow Size指的是该对象本身占用内存的大小,Retained Size代表该对象被释放后,垃圾回收器能回收的内存总和。
下面我们以掌上道聚城客户端为例,来一探内存泄漏检测的方法。
打开Android Studio,编译代码,运行掌上道聚城,然后开始尽情的耍我们的App啦,然后就从Memory Monitor里面观察App的内存使用曲线,突然发现,纳尼!!!怎么内存使用越来越大了,这就很有可能是发生内存泄漏了,然后点击手动进行GC,再点击观看JavaHeap,点击Analyzer Task,Android Monitor就可以为我们自动分析泄漏的Activity啦,分析出来如下图所示

在Reference Tree里面,我们直接就可以看到持有该Activity的单例对象,直接定位到该单例中的代码,发现代码中出现了

public static VideoTagHelper getInstance(Context context) {
        if (tagHelper == null) {
            tagHelper = new VideoTagHelper();
        }
        tagHelper.context = context;
        return tagHelper;
    }

和刚刚举得栗子里出现的错误一模一样啊,这段代码是谁写的,拖出去······
我们修复了检查出的内存泄漏的问题,并将修复前和修复后的代码在相同的模拟器上运行并进行相同的操作,查看他们使用内存的情况,如下图所示


有内存泄漏的情况,占用内存约为43M

修复了内存泄漏问题,占用内存为36M
在修复了内存泄漏问题后,内存使用下降了16.3%!!!
掌握了Android Monitor的使用方法后,妈妈再也不担心我写的App会出现内存泄漏啦!!!


android studio 1.5 为例:






### Android Studio 如何检测内存泄漏Android 开发中,内存泄漏是常见的问题,而 Android Studio 提供了强大的工具来帮助开发者检测解决这些问题。以下是几种常用的方法和工具: #### 使用 Android Profiler Android Studio 3.0 及以上版本引入了 **Android Profiler**,这是一个内置的性能分析工具,可以实时监控应用的 CPU、内存、网络和能源使用情况。通过内存分析功能,开发者可以检测内存泄漏的迹象。 - 打开 **Android Profiler**,选择设备和应用进程后,点击 **Memory** 面板。 - 在内存面板中,可以看到应用的内存使用情况,包括 Java 堆内存的使用。 - 点击 **Dump Java heap** 按钮,可以生成当前堆内存的快照。 - 通过分析快照中的对象,可以找到可能存在的内存泄漏。例如,如果某个 Activity 或 Fragment 的实例在不应该存在的时候仍然存在,可能是内存泄漏的迹象。 #### 使用 LeakCanary 插件 LeakCanary 是一个开源的内存泄漏检测库,专为 Android 设计。它可以自动检测应用中的内存泄漏,并在通知栏中显示提示信息。 - 在项目的 `build.gradle` 文件中添加 LeakCanary 的依赖: ```gradle dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' } ``` - 在 `Application` 类中初始化 LeakCanary: ```java public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); if (LeakCanary.isInAnalyzerProcess(this)) { // This process is dedicated to LeakCanary for heap analysis. // You should not init your app in this process. return; } LeakCanary.install(this); } } ``` - 运行应用后,LeakCanary 会自动检测内存泄漏,并在通知栏中显示提示信息。点击通知,可以查看详细的泄漏路径和原因。 #### 使用 MAT (Memory Analyzer Tool) MAT 是一个基于 Eclipse 的内存分析工具,能够 Android Studio 配合使用,帮助开发者深入分析内存泄漏的原因。 - 在 Android Studio 中生成堆内存快照后,导出 `.hprof` 文件。 - 将 `.hprof` 文件导入到 MAT 中,使用 **Histogram** 或 **Dominator Tree** 功能分析内存使用情况。 - 通过查看对象的引用链,可以找到导致内存泄漏的具体原因。 #### 示例代码:检测内存泄漏的 Activity 以下是一个简单的示例代码,展示了如何通过 Android Profiler 检测内存泄漏的 Activity: ```java public class TestActivity extends AppCompatActivity { private static Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); context = this; // 导致内存泄漏的静态引用 } @Override protected void onDestroy() { super.onDestroy(); context = null; // 解决内存泄漏 } } ``` 在上述代码中,`context` 是一个静态变量,指向了 `TestActivity` 的实例。如果不及时将其置为 `null`,可能会导致内存泄漏。通过 Android Profiler 或 LeakCanary,可以检测到这一问题。 #### 总结 通过 Android Studio 的内置工具(如 Android Profiler)和第三方库(如 LeakCanary),开发者可以有效地检测解决内存泄漏问题。结合 MAT 工具,可以进一步深入分析内存泄漏的根本原因。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值