利用Android Studio、MAT对Android进行内存泄漏检测

2024-09-01 04:48

本文主要是介绍利用Android Studio、MAT对Android进行内存泄漏检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自:http://www.cnblogs.com/taoweiji/p/5760537.html

Android开发中难免会遇到各种内存泄漏,如果不及时发现处理,会导致出现内存越用越大,可能会因为内存泄漏导致出现各种奇怪的crash,甚至可能出现因内存不足而导致APP崩溃。

内存泄漏分析工具

Android的内存泄漏分析工具常用有Android Studio和基于eclipse的MAT(Memory Analyzer Tool)。通过两者配合,可以发挥出奇妙的效果。Android Studio能够快速定位内存泄漏的Activity,MAT能根据已知的Activity快速找出内存泄漏的根源。

第一步:强制GC,生成Java Heap文件

我们都知道Java有一个非常强大的垃圾回收机制,会帮我回收无引用的对象,这些无引用的对象不在我们内存泄漏分析的范畴,Android Studio有一个Android Monitors帮助我们进行强制GC,获取Java Heap文件。

强制GC:点击Initate GC(1)按钮,建议点击后等待几秒后再次点击,尝试多次,让GC更加充分。然后点击Dump Java Heap(2)按钮,然后等到一段时间,生成有点慢。

生成hprof文件

生成的Java Heap文件会在新建窗口打开。

Analyzer Tasks

第二步:分析内存泄漏的Activity

点击Analyzer TasksPerform Analysis(1)按钮,然后等待几秒十几秒不等,即可找出内存泄漏的Activity(2)。

Analyzer_Tasks_2

那么我们就可以知道内存泄漏的Activity,因为这个例子比较简单,其实在(3)就已经可以看到问题所在,如果比较复杂的问题Android Studio并不够直观,不够MAT方便,如果Android Studio无法解决我们的问题,就建议使用MAT来分析,所以下一步我们就生成标准的hprof文件,通过MAT来找出泄漏的根源。

第三步:转换成标准的hprof文件

刚才生成的Heap文件不是标准的Java Heap,所以MAT无法打开,我们需要转换成标准的Java Heap文件,这个工具Android Studio就有提供,叫做Captures,右击选中的hprofExport to standard .hprof选择保存的位置,即可生成一个标准的hprof文件。

standard_hprof.png

第四步:MAT打开hprof文件

MAT的下载地址,使用方式和eclipse一样,这里就不多说了,打开刚才生成的hprof文件。点击(1)按钮打开Histogram。(2)这里是支持正则表达式,我们直接输入Activity名称,点击enter键即可。

Histogram_1

搜索到了目标的Activity

Histogram_2

右击搜索出来的类名,选择Merge Shortest Paths to GC Rootsexclude all phantom/weak/soft etc. references,来到这一步,就可以看到内存泄漏的原因,我们就需要根据内存泄漏的信息集合我们的代码去分析原因。

Histogram_3

第六步:根据内存泄漏信息和代码分析原因

使用Handler案例分析,给出的信息是Thread和android.os.Message,这个Thread和Message配合通常是在Handler使用,结合代码,所以我猜测是Handler导致内存泄漏问题,查看代码,直接就在函数中定义了一个final的Handler用来定时任务,在Activity的onDestroy后,这个Handler还在不断地工作,导致Activity无法正常回收。

// 导致内存泄漏的代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
textView = (TextView) findViewById(R.id.text);
final Handler handler = new Handler();
handler.post(new Runnable() {@Overridepublic void run() {textView.setText(String.valueOf(timer++));handler.postDelayed(this, 1000);}});
}
修改代码,避免内存泄漏
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
textView = (TextView) findViewById(R.id.text);
handler.post(new Runnable() {@Overridepublic void run() {textView.setText(String.valueOf(timer++));if (handler != null) {handler.postDelayed(this, 1000);}}
});
}
private Handler handler = new Handler();
@Override
protected void onDestroy() {super.onDestroy();// 避免Handler导致内存泄漏handler.removeCallbacksAndMessages(null);handler = null;
}

重新测试,确保问题已经解决。

文章代码

https://github.com/taoweiji/DemoAndroidMemoryLeak

这篇关于利用Android Studio、MAT对Android进行内存泄漏检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125984

相关文章

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

Python脚本轻松实现检测麦克风功能

《Python脚本轻松实现检测麦克风功能》在进行音频处理或开发需要使用麦克风的应用程序时,确保麦克风功能正常是非常重要的,本文将介绍一个简单的Python脚本,能够帮助我们检测本地麦克风的功能,需要的... 目录轻松检测麦克风功能脚本介绍一、python环境准备二、代码解析三、使用方法四、知识扩展轻松检测麦

MySQL进行分片合并的实现步骤

《MySQL进行分片合并的实现步骤》分片合并是指在分布式数据库系统中,将不同分片上的查询结果进行整合,以获得完整的查询结果,下面就来具体介绍一下,感兴趣的可以了解一下... 目录环境准备项目依赖数据源配置分片上下文分片查询和合并代码实现1. 查询单条记录2. 跨分片查询和合并测试结论分片合并(Shardin

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

SpringBoot结合Knife4j进行API分组授权管理配置详解

《SpringBoot结合Knife4j进行API分组授权管理配置详解》在现代的微服务架构中,API文档和授权管理是不可或缺的一部分,本文将介绍如何在SpringBoot应用中集成Knife4j,并进... 目录环境准备配置 Swagger配置 Swagger OpenAPI自定义 Swagger UI 底