美文网首页Android 面试集Android知识Android开发
使用Android Monitor分析项目查找内存泄漏

使用Android Monitor分析项目查找内存泄漏

作者: 明朗__ | 来源:发表于2017-04-03 16:13 被阅读911次

    前言:
    在开发项目的过程中 或多或少都有些地方不注意造成内存泄漏导致App卡顿的情况发生 Android Studio也为我们提供了一些查找内存泄漏的组件 今天就先学习下 如何使用Android Monitor来分析和查找项目中内存泄漏的地方

    案例:

    public class CommUtil {
        private static CommUtil instance;
        private Context context;
        private CommUtil(Context context) {
            this.context=context;
        }
        public static CommUtil getInstance(Context context){
            if(null==instance){
                instance=new CommUtil(context);
            }
            return instance;
        }
    }
    
    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            CommUtil instance = CommUtil.getInstance(this);
        }
    }
    

    将Activity的实例被一个单例对象所持有,相信这样的代码错误大家应该不会去犯,这里主要学习如何使用Android Monitor 就迁就一下,然后我们运行起来 ,再将手机屏幕旋转几下(旋转屏幕的时候 Activity会被销毁重新创建,但是这里的单例会持有销毁Activity的实例就造成内存泄漏)。


    1. 先看看Android Studio 的Android Monitor都有哪些功能 先只关注Memory这块


      Initiate Gc:点击主动去回收垃圾内存
      Dump java Heap: 点击就会生成app运行内存快照.hprof文件
      Free :代表还剩下的内存
      Allocated:代表已经使用的内存
    2. Dump java Heap点击就会生成app运行内存快照.hprof文件

    3. 通过内存快照 看到MainActivity 在内存中有3个实例 点击进行进一步查看


      Depth:对象被引用的深度
      Shallow Size:对象实例的大小
      Dominating Size:对象管辖范围的内存大小
    4. 在Instance区域我们看到了MainActivity的3个实例对象 已经各个对象的引用深度和大小等 这里就明显看到了MainActivtiy内存泄漏了 这里说明一下 (在运行项目的时候 手机屏幕旋转了3下 所以生成了3个MianActivity实例 但是第二个MainActivity已经被回收 因为当GC回收的时候会将除了第0个和最后这一个留着其他的都会被回收 所以当你把手机屏幕旋转3次以上的时候 内存里面只会有2个Activity实例)
      点击编号2的MianActivity进行查看:


      Depth:对象被引用的深度
      Shallow Size:对象实例的大小
      Dominating Size:对象管辖范围的内存大小
    5. 根据上面的内存对象引用树就能得出结论分析(除CommUtil以外的地方是系统级的引用这里暂时先不用管) :

      • CommUtil引用了MainActivity的context
      • 引用深度Depth为1 对象大小为12 该对象管辖范围大小为60781
        然后改代码:
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            CommUtil instance = CommUtil.getInstance(getApplicationContext());
        }
    }
    
    1. 该代码运行 且旋转屏幕后 再生成内存快照.hprof文件查看:



      将this改为getApplicationContext()后 MainActivity在几次旋转屏幕后始终保持一个实例

    总结:

    • 以上是通过已知案例来进行对Android Monitor的简单学习 在实际开发过程中还需要去仔细的分析(这个相对来讲较困难 需要根据自己的一些经验来看)

    最后:

    • 其实还有一个工具叫MAT Memory Analyzer 如何使用在下篇文章进行讲解

    相关文章

      网友评论

      • 相互交流:楼主还知道其他检测工具吗?
      • MiBoy:楼主没有解释清楚,为什么设置了applicationcontext之后就不会内存泄露了
        MiBoy:@MiBoy 嗯,其实可以这样理解吧,传入的是applicationContext.其实和activity一点关系都没有了,你再怎么销毁创建也不会持有你。
        明朗__:因为getApplicationContext()获取的是Application的Context 生命周期随APP运行结束而结束 而this代表当前Activtiy finish()后就销毁了 。
      • MiBoy:其实一开始也想做一个这个工具的文章,但是还是没动手。补充一个小技巧,左上方可以按包名去筛选,也是很方便。
        明朗__:是的 选择Package Tree View 就可以以包名的方式去筛选

      本文标题:使用Android Monitor分析项目查找内存泄漏

      本文链接:https://www.haomeiwen.com/subject/tyfoottx.html