MAT内存分析详细步骤

MAT内存分析详细步骤
写的贼好:https://www.cnblogs.com/tangZH/p/10955429.html
泄漏,泄漏,漏~
内存泄漏怎么破,什么是内存泄漏?与内存溢出有什么区别?

内存泄漏(Memory Leak):是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;

内存泄漏不一定会引起奔溃,但是内存溢出一定会

Java里头有GC垃圾回收机制,他是怎么判断该不该回收呢?
在这里插入图片描述

Q1:某对象没有任何引用的时候才进行回收?
A:不。无法往上追溯到GCroot引用点的才回收。

Q2:某对象被别的对象引用就不能进行回收?
A:不。软引用,弱引用,虚引用都可以


哪些可以作为GCroot引用点:
Javastack中引用的对象
方法区中静态引用指向的对象
方法区中常量引用指向的对象
Native方法中JNI引用指向的对象
Thread-活着的线程

adb命令验证是否存在内存泄漏:
1、打开要测试的apk,然后返回退出到主界面
2、AS的Terminal中输入命令:
adb shell dumpsys meminfo com.status.mattest -d
com.status.mattest为包名

然后便可以看到内存的一些情况
拉到下面可以看到:
在这里插入图片描述

我们退出APK之后,对象本应该都被回收,然而这里可以看到,还有view以及Activity占用着内存,由此可以知道内存泄漏了。


我们点击AS上的按钮,进行分析。
在这里插入图片描述

运行apk后会出现该界面:
在这里插入图片描述

我们点击MEMORY进入内存分析界面:
在这里插入图片描述

这时候我们需要进行刚刚的操作,打开apk,然后返回键退出,然后点击上图中垃圾桶形状的图标进行垃圾回收,多点几次,直到内存没有什么变化了。
然后点击上图中类似于下载按钮的图标获取内存快照。
在这里插入图片描述

获取完之后,左边会出现下面这图,Head Dump便是获取内存快照后出现的,我们可以点击红圈中的图形进行保存
在这里插入图片描述

跟着出现的还有这个窗口。
在这里插入图片描述

我们可以通过包来分类查看自己的项目.
Shallow Heap(浅堆) 表示该对象自身占用的堆内存,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。
Retained Heap(深堆) 表示当前对象大小+当前对象可直接或间接引用到的对象的大小总和。
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。

不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
从图中可以看出,出现了内存泄漏的是CustomUtils,MainActivity,MainActivity$1代表MaiActivity里面的一个方法。

点击MainActivity,可以看到这么对东西,眼花缭乱,我们根本不知道是哪个引起了内存泄漏。那咋办。铺垫结束,mat该上场了。
在这里插入图片描述

MAT
下载mat https://www.eclipse.org/mat/downloads.php
安装步骤很简单。

打开MAT后,点击File -> Open Heap Dump 打开刚刚保存的内存快照,会发现打不开。
在这里插入图片描述

因为我们保存的内存快照是不能直接在MAT上打开的,需要进行转化。

在AS的Terminal窗口输入:hprof-conv -z A.hprof B.hprof
A.hprof为刚刚保存后的快照文件,B.hprof为转换后的文件,也就是我们要在MAT上打开的文件
在这里插入图片描述

然后我们在MAT上将其打开。
在这里插入图片描述

点击Finish

在这里插入图片描述

点击Histogram
在这里插入图片描述

可以通过包名来分类查看
在这里插入图片描述

从下图中可以看到引起内存泄漏的类,Objects那一列不为0的就是,与我们之前看到的一样。

MainActivity右键
在这里插入图片描述

选择图中的选项,意思是过滤掉虚引用,软引用,弱引用
在这里插入图片描述

之后可以看到引用的路径,CustomUtils里面的instance引用了MainActivity的context,导致了MainActivity内存泄漏。
打开代码看一下

package com.status.mattest;

import android.content.Context;

public class CustomUtils {
private static CustomUtils instance;

private CustomUtils(Context context) {
    this.mContext = context;
}

private Context mContext;

public static CustomUtils getInstance(Context context) {
    if (instance == null) {
        instance = new CustomUtils(context);
    }

    return instance;
}

}

MainActivity中:

package com.status.mattest;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    CustomUtils customUtils = CustomUtils.getInstance(this);
    textView = findViewById(R.id.tv);
    textView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startActivity(new Intent(MainActivity.this, Test1Activity.class));
        }
    });
}

}

MainActivity中调用了单例CustomUtils,并且把context传了进去,而我们知道instance作为静态对象,是GCroot引用点,所以activity关闭了它也没法被回收,那么最为被instance引用的Activity自然也无法被回收,所以导致了内存泄漏。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值