关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。
我们继续总结学习Android 基础知识,温故知新。
内存泄漏(Memory leak)是指程序在运行过程中分配的内存资源没有被正确释放,导致这部分内存无法再被程序使用,最终消耗了系统的可用内存。
内存泄漏可能会导致以下问题:
内存泄漏的原因可能包括:
在开发过程中,可以使用内存分析工具来检测和解决内存泄漏问题,如内存检测工具、代码审查等。
不同的工具有不同的使用场景,对应线下场景,我们先用 android studio自带的工具,
我们捕获堆转储文件分析
//匿名内部类
private Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg){
super.handleMessage(msg);
}
}
我们先说下原因,匿名内部类默认持有外部类的引用,如果这个mHandler有个延时任务未执行,此时退出activity页面,
此时Handler又持有Activity的引用,导致GC无法回收Activity,导致内存泄漏。
将上面的堆转储另存为 HPROF 文件,再用mat打开
hprof-conv heap-original.hprof heap-converted.hprof
我们直接通过OQL语法来排查内存泄漏,如上图箭头所示的地方,我们在oql页面输入下面的查询代码,然后按下图中红色的小箭头,
select * from instanceof android.app.Activity
会在下面出现查询结果,如下图所示,可以看到,查询到了9个一样的 MemoryShakeActivity,这肯定是有问题的 ,
那我们如何确认是哪里有问题呢?
我们在其中一个activity上右键点击,然后会出现一个菜单,选择 path to gc root, 再选择最长的那个选项 exclude all …
最终,我们在mat里面会出现一个新的页面,也就找到了内存泄漏的地方,看下图:
它可以列出任意一个类的实例数(每个对象的统计)。它支持使用正则表达式来查找某个特定的类,还可以计算出该类所有对象的保留堆最小值或者精确值,
我们可以通过正则表达式输入 MemoryShakeActivity, 看到Histogram列出了与 MemoryShakeActivity 相关的类
然后选中一行,然后依次选择,点击右键 -> Merge Shortest Paths to GC Roots -> exclude all phantom/weak/soft etc.references(排查虚引用/弱引用/软引用等)
然后我们就可以看到哪里泄漏了
Merge Shortest Paths to GC Roots 可以查看一个对象到RC Roots是否存在引用链相连接,
在JAVA中是通过可达性(Reachability Analysis)来判断对象是否存活,这个算法的基本思想是通过一系列的称谓"GC Roots"的对象作为起始点,
从这些节点开始向下搜索,搜索所走得路径称为引用链,当一个对象到GC Roots没有任何引用链相连则该对象被判定为可以被回收的对象,反之不能被回收,
虚引用/弱引用/软引用的对象可以直接被GC给回收.
Dominator Tree(支配树)提供了程序中最占内存的对象的排列。
使用方法跟Histogram(直方图)差不多,按照上面类似的操作即可。
Java 专栏
SQL 专栏
数据结构与算法
Android学习专栏