Android 内存泄露分析

Android Studio 分析内存泄漏 内存分析入门 阅读详情

编程工具:Android Studio
分析内存工具:Android Studio和MAT

内存泄露的例子:

// MainActivity类
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void openNextActivity(View view) {
        // 跳转到内存泄露的Activity
        startActivity(new Intent(this, SecondActivity.class));
    }
}
// SecondActivity类 : 存在内存泄露
public class SecondActivity extends AppCompatActivity {
    private List<Student> dataList = new ArrayList<>();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        // 模拟储存10000个数据,这样更分析更明显
        for (int i = 0; i < 10000; i++) {
            dataList.add(new Student("test" + i, i, "school" + i));
        }
        new Thread(runnable).start();
    }
    public static class Student {
        public String name;
        public int age;
        public String school;
        public Student(String name, int age, String school) {
            this.name = name;
            this.age = age;
            this.school = school;
        }
    }
    // 内存类,依赖外部类,持有外部类SecondActivity实例
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // 模拟延时
            try {
                Thread.sleep(100 * 60 * 60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
}

初步分析

我们可以利用Android Studio的【Monitors窗口】查看应用内存情况:

用于对比,先把存在内存泄露的Activity恢复正常:

// SecondActivity类 : 不存在内存泄露问题
public class SecondActivity extends AppCompatActivity {
    private List<Student> dataList = new ArrayList<>();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        // 模拟储存10000个数据,这样更分析更明显
        for (int i = 0; i < 10000; i++) {
            dataList.add(new Student("test" + i, i, "school" + i));
        }
    }
    public static class Student {
        public String name;
        public int age;
        public String school;
        public Student(String name, int age, String school) {
            this.name = name;
            this.age = age;
            this.school = school;
        }
    }
}

然后反复启动10-20次SecondActivity,内存使用情况是这样的:

从结果可以看到,几次GC之后,内存可以正常被回收。

我们来看看SecondActivity存在内存泄露的情况:

对比上一个图,几次GC之后,程序占用的内存一直上升,说明本该被回收的内存一直没有被释放。初步分析,存在内存泄露问题。

接下来我详细分析哪里存在内存泄露。

进一步分析

Android Studio自带的界面,查看内存泄露还不是很智能,我们可以借助第三方工具。
常见的工具就是MAT了,下载地址 http://eclipse.org/mat/downloads.php ,这里我们需要下载独立版的MAT。

生成hprof文件

hprof文件可以让Android Studio帮我们生成,具体做法是:

启动程序,MainActivity中点击按钮跳转到SecondActivity(初步分析,存在内存泄露),返回点击返回键,然后点击按钮跳转到SecondActivity,再点击返回,反复几次,然后点击【Monitors窗口】下【Momery】右边的【Dump Java Heap】按钮:

此时hprof文件已经生成了,在【Captrues窗口】可以找到:

但是此时的hprof文件还不能被MAT识别,我们右击我们需要的hprof文件,导出标准的hprof文件:

分析hprof文件

我们用MAT分析内存工具打开导出的hprof文件:

打开之后,点击工具栏中的直方图图标查看内存详细情况(就是哪些类使用了多少内存):

打开的界面会显示所有的内存使用情况,所以需要我们过滤一下(一般关键字为包名):

过滤之后显示的界面是这样的:

我们从这里可以看到,因为SecondActivity被我启动了7次,产生了7个SecondActivity实例,而且都没有回收,因为每个SecondActivity实例都保存了10000个Student实例,所以Student实例有70000个,我们查查SecondActivity为什么没有被回收。

右击【com.johan.demo.SecondActivity】,选择【Merge Shortest Paths to GC Roots】,然后选择【with all reference】:

然后展开一个查看:

发现SecondActivity实例被Thread匿名内部类的this$0引用,Thread还存活,所以持有的SecondActivity实例也认为是“存活”的,所以GC不能回收,造成内存泄露。

这就找到了内存泄露的原因!!

SecondActivity内存泄露的原因是静态内部类持有外部类导致的,我们这么改造一下:

public class SecondActivity extends AppCompatActivity {
    private List<Student> dataList = new ArrayList<>();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        for (int i = 0; i < 10000; i++) {
            dataList.add(new Student("test" + i, i, "school" + i));
        }
        new Thread(new MyRunnable()).start();
    }
    public static class Student {
        public String name;
        public int age;
        public String school;
        public Student(String name, int age, String school) {
            this.name = name;
            this.age = age;
            this.school = school;
        }
    }
    // 声明为静态内部类
    public static class MyRunnable implements Runnable {
        @Override
        public void run() {
            // 模拟延时
            try {
                Thread.sleep(100 * 60 * 60 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我们重新导出hprof文件,查看内存详细情况:

如图,MyRunnable对象有7个,证明SecondActivity已经启动了7次,而SecondActivity只剩下一个(应该是还没有来得回收),所以SecondActivity实例可以被GC正常回收了,内存泄露问题得以解决!!其实这里还有泄露,就是MyRunnable,我们关闭SecondActivity的时候,应该中断线程。不过还是建议使用线程池,靠谱!

LeakCanary

目前除了导出hprof文件分析内存泄露,还有一种更简单的办法,就是在程序代码中集成LeakCanary。

项目地址:https://github.com/square/leakcanary

有兴趣的自己试一下!!!

Android待机问题与内存泄露日志定位及bugreport获取分析 安卓 bugreport 是 Android 系统生成的错误报告文件,它可以帮助开发者和技术支持人员诊断和解决系统或应用程序出现的问题。 1. 分析bugreport,定位唤醒源,判断是否有ANR。 2. 分析安卓log,定位待机唤醒功耗问题,判断是否有内存泄露。 阅读详情

相关推荐

Android常见内存泄露分析及MAT与Profiler内存分析时间

1.Java内存分配策略 Java程序运行时的内存分配策略有三种:静态分配、栈式分配和堆式分配。对应的存储区域如下: 静态存储区(方法区):主要存放静态数据、全局static数据和常量。这块内存在程序编译时就已经分配好,并且在程序整个运行期间都存在。 栈区:方法体内的局部变量都在栈上创建,并在方法执行结束时这些局部变量所持有的内存都会自动被释放。 堆区:又称动态内存分配,通常就是指在程序运行时直接new出来的内存。这部分内存在不使用时将会由Java垃圾回收器来负责回收。 2.堆与栈的区别 栈内存:

Tiger的专栏 1304

Activity的四大启动方式&&启动Activity引起的内存泄露问题

前情提要作为一个安卓程序猿,挣钱问题深深的困扰着我们,但是内存泄露像一座大山,阻挡在我们面前,我们必须干掉他,继续向前。![1](http://img.blog.youkuaiyun.com/20171018204612741?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2gxNDA2Mjg1MjQ2/font/5a6L5L2T/fontsize/400/fill

ch1406285246的博客 824

Android Studio中把llama.cpp编译Android .so

本文介绍了一个在Android Studio中集成llama.cpp的最小Demo实现方案,通过JNI将llama.cpp编译为Android.so库,实现本地加载GGUF模型进行文本生成。文章详细说明了项目结构配置(SDK≥30,NDK≥28)、CMake编译设置、Kotlin-JNI-C++的完整调用链实现,以及模型文件部署方式。该Demo采用每次请求新建上下文的简化设计,包含加载模型、生成文本、资源释放等核心功能,并提供了错误排查建议。项目舍弃了上下文保持等复杂功能以确保稳定性,适合作为端侧大语言模型

Zhang Phil 516

Android 中 Activity的内存泄漏,原因以及处理方法

文章参考: 八个造成 Android 应用内存泄露的原因 Android内存泄漏产生的原因以及解决方案OOM 内存泄漏,说的更直白点,就是你想让一个对象在下次GC的时候彻底被回收,但是呢,这个对象所处的条件不符合GC所认定的应当回收的条件,而导致实际上没有被回收依然占用着内存空间,像这样的对象多了,,迟早会把内存撑爆引发大名鼎鼎的OOM问题。Android中最最露骨的就是Activity的内...

童年纸飞机的博客 6734

初识YUV,实战NV21格式数据转换为Bitmap

初识YUV,并使用YUV数据生成Bitmap图像一、初识YUV二、采样方式2.1、YUV 4:4:42.2、YUV 4:2:22.2、YUV 4:2:2 一、初识YUV 说到YUV我们就必须先从RGB说起了,如下图所示,请各位把每个色块当成一个像素点。通常一个像素点由RGB(Alpha我们先不考虑)三原色组成。 如下图中第一个像素点,其RGB值分别为(236,102,93),而这三个值就组成了我们看到的 红色 。 然而上图中除了RGB值外,我还标出了每个像素点的YUV的值,YUV的值是怎么来的呢?直接给公

乐翁龙 7125

整合WGCNA、机器学习和孟德尔随机化

(G)通过蛋白质免疫印迹法(Western blot)测定的 UT-B(由 SLC14A1 编码)、ARHGEF38、NEFH、MSMB、KRT23 和 KRT15 在前列腺癌肿瘤组织和癌旁非癌组织中的蛋白质表达水平。本研究利用来自基因表达综合数据库(GEO)的数据集筛选差异表达基因(DEGs),并采用加权基因共表达网络分析(WGCNA),以识别在模块中与前列腺癌高度相关的驱动基因。(F)蓝绿色模块中的模块成员关系(MM)与前列腺癌(PCa)的基因显著性(GS)的散点图。(D)6 个基因之间的相关性分析。

多组・学・多组学 1137

Android内存优化方案和内存泄露检测分析方法

常见内存泄露及优化方案1、单例错误写法:public class AppSettings { private static AppSettings sInstance; private Context mContext; private AppSettings(Context context) { this.mContext = context; }

扣子Coze大师班 2498

小米汽车技术路线

从小米的电子电器架构来看,行业内EEA已经由域集中逐渐过度到域融合+区域控制的架构并向着中央计算+区域控制的方向发展。 而小米汽车智驾算法也从基于高精地图模块化架构,到去高精地图模块化架构,再到端到端架构,这也正是行业对于智驾算法演进的共识。

HITbingdu的博客 3785

android 内存泄露分析方法,Android内存泄露的分析方法

前言内存泄露,这个耳熟能详的一个bug,每次我在项目中遇到这种问题都非常的头疼,不像普通的异常奔溃比如JE什么的,只要通过Log中的异常堆栈就可以轻松的定位出问题点。那么到底什么是内存泄漏呢?简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收。导致这种情况原因是生命周期长的对象持有了生命周期短的对象导致的生命周期短的对象无法被回收。要想定位出内存泄...

weixin_39667452的博客 287

常见信号逻辑电平标准介绍:TTL、CMOS、ECL、LVDS、CML

逻辑电平是指数字信号电压的高、低电平,相关参数定义如下:(1)输入高电平门限Vih:保证逻辑门的输入为高电平时所允许的最小输入高电平,当输入电平高于Vih时,则认为输入电平为高电平;(2)输入低电平门限Vil:保证逻辑门的输入为低电平时所允许的最大输入低电平,当输入电平低于Vil时,则认为输入电平为低电平;(3)输出高电平门限Voh:保证逻辑门的输出为高电平时的输出电平的最小值,逻辑门的输出为高电平时的电平值都必须大于此Voh;

liuchj的博客 1万+

Hugging Face 最新开源 SmolVLA 小模型入门教程(一)

今天,我们介绍SmolVLA,这是一个紧凑型(450M)、开源的视觉-语言-动作模型,专为机器人设计,可在消费级硬件上运行。 仅在带有lerobot标签的开源社区共享数据集上进行预训练。 SmolVLA-450M在模拟环境(LIBERO、Meta-World)和真实世界任务(SO100、SO101)中,表现优于规模更大的VLA模型及强基线模型如ACT。 支持异步推理,响应速度提升30%,任务吞吐量提升2倍。

2506_90492529的博客 4078

android 内存泄露实战分析

前两天测试测出一个内存泄露问题,困扰了我好几天,毫无头绪,今天突然灵光一现,找到了问题原因,解决了内存泄露问题,解决方法很简单,但是总要的是问题分析过程,所以有比较把解决问题思路记录下来,以便后续分析类似问题有参考作用,一下进入正题。以上是性能测试同事测出的问题,红框的地方表示电话应用出现了三个泄露,遇到这种问题,咱们先拿到hprof问题,拿不到就找测试要或者自己跑对应的测试用例,测试方法也可以找测试要,拿到hprof文件后,使用android studio的profiler打开:已上片是我自己抓取的hpr

limeng的博客 2519

YOLO26改进策略【模型轻量化】| 替换骨干网络为 2024轻量化网络MoblieNetV4:移动生态系统的通用模型

本文记录的是基于MobileNet V4的YOLO26目标检测轻量化改进方法研究。主要用于轻量化应用部署,相关轻量化改进与其整体架构非常适配。通过整合、以及优化的,能够在在不降低性能指标的前提下,降低计算成本。本文配置了原论文中、、、和五种模型,以满足不同的需求。MobileNetV4: Universal Models for the Mobile Ecosystem是一系列适用于移动生态系统的通用高效模型。以下将详细介绍其轻量化设计的出发点、原理、结构和优势:的实现代码如下: 四、修改步骤 4.1 修

Limiiiing的博客 827

Android--内存泄露分析

一、内存泄露 java中的内存泄露是指一个无用对象持续占有内存或无用对象的内存得不到及时的释放,从而造成的内存控件的浪费称为内存泄露。 强引用(StrongReference):JVM 宁可抛出 OOM ,也不会让 GC 回收具有强引用的对象; 软引用(SoftReference):只有在内存空间不足时,才会被回的对象; 弱引用(WeakReference):在 GC(垃圾回收) 时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存; 虚引用(Phant...

超宇的博客 2340

解锁IPG Photonics SmartWeld系统,开启焊接新时代

SmartWeld 系统是 IPG Photonics 研发的一款先进的激光焊接解决方案,它隶属于自动化激光焊接系统类别 ,但却凭借一系列创新技术和独特设计,在众多同类产品中脱颖而出。该系统基于 IPG 在光纤激光技术领域的深厚积累,融合了先进的光束控制、智能监测和自动化控制等技术,旨在为工业制造提供高效、精准且稳定的焊接工艺。与传统激光焊接系统相比,SmartWeld 系统的独特之处首先体现在其光束控制技术上。它能够精确地调整激光束的能量分布、光斑大小和形状 ,以适应不同材料和焊接工艺的需求。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 1429

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Android 内存泄露及LeakCanary分析

Java中的WeakReference是弱引用类型,每当发生GC时,它所持有的对象如果没有被其他强引用所持有,那么它所引用的对象就会被回收,同时或者稍后的时间这个WeakReference会被入队到ReferenceQueue中,LeakCanary中检测内存泄露就是基于这个原理。:原因如上,Handler持有外部类的引用,Message持有Handler的引用,MessageQueue持有Message的引用,Looper持有MessageQueue的引用,Looper一直存在,导致引用链都不会被回收;

行知致简的专栏 2256

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Android Studio自带Profiler工具内存泄露分析步骤

1、运行需要检测内存泄露的程序 这里以“com.example.opengltest”程序为例。 2、点击Profiler按钮 3、点击SESIONS "+"号按钮选择设备,选择对应设备下的应用或进程 4、双击内存区块 5、操作应用程序要检测的部分或模块 6、关闭应用程序,等待内存释放,恢复平直曲线 7、点击鼠标右键“Dump java head”按钮等待几秒 自动进入内存泄露分析界面 8、选择应用包名 9、选择“Reference”按钮,勾选“Show nearest.

hqyhqyhq的专栏 2万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android开发 内存泄露抓取与分析

前言   这篇博客鸽了很久, 时间是一方面,另一方本人其实很菜.测试转开发对底层,半路出家对底层的认知非常少. 所以,这篇博客之前的内容已经全部删除了. 现在更新全新内容.主要是两个方面 捕获与分析内存泄露 发生内存泄露的例子 捕获内存泄露   这里并不打算使用内存泄露检测框架LeakCanary(这是捕获内存泄露的好工具,适合在黑盒测试时一起使用,缺点是没办法实时观察内存泄露与内存情况,并...

cherish152的博客 97

android内存泄露问题分析,内存泄露实例分析 -- Android内存优化第四弹

引言前文内存分析工具集中介绍了一系列的内存分析工具及其基本使用, 诸如Memory Monitor, HPROF Viewer, MAT等等. 实际上了解了工具的使用, 我们就已经掌握了如何分析内存问题了.为了能对工具的使用更加深入, 本篇将一个代码片段为例, 从时序的角度讲解下如何使用这些工具来分析一个内存泄露.1, 例子假设有一个单例的ListenerManager, 可以add / remo...

weixin_34355977的博客 307

安卓Native Memory Leak(本地服务内存泄露)分析

当我们分析app的内存泄露时,使用Android Studio自带的profile工具可以比较方便,但是当我们需要调试一些c/c++本地服务进程的时候就不是很方便了。这里跟的是需要调试的进程名,如果我们需要调试android.hardware.camera.provider@2.4-service这里就是。这种方法就是malloc_debug,这是安卓自带的调试工具,基于libc来实现,通过截取我们的调用堆栈来监控内存使用情况。其中的参数选项可根据自己的需求来添加,具体参数解释可阅读readme。...

superjaingchao的专栏 1573

Android 性能优化之使用MAT分析内存泄露问题

我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android设备的参差不齐,可能运行在这台设备好好的,运行在那台设备就报OOM,这些适配问题也是比较蛋疼的,比如我们平常运行着一个应用程序,运行的好好的,突然到某个Activity就给你爆出一个OOM的错误,你可能会以为是这个Activity导致的内存泄露,你会想到也有可能是内存有泄露吗?内存泄露就像一个定时炸弹,随时都有

Mobile Internet developer 4万+

Android内存泄露监控和分析应用

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的最后,互联网不存在所谓的寒冬,只是你没有努力罢了!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!**

2401_84132479的博客 459

android studio 内存泄露,Android Studio + MAT 内存泄露分析

前提 ThirdActivity 已经关闭,回到了MainAcitivity。应该是只有回到了MainAcitivity的。通过 Profiler 看到还有 ThirdActivity,那就是它有内存泄露。image1、首先利用 Profiler GC 打点,下载 hpof。当然也可以在Profiler中查看Activity是否有泄露,但是具体不到在哪里。2、下载 MAT http://eclip...

weixin_30380991的博客 218
上一篇: Android 常见的内存泄露
下一篇: Android 组件化之路 路由设计
JohanMan
博客等级 码龄10年 72粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值