Android 内存优化】垃圾回收算法 ( 内存优化总结 | 常见的内存泄漏场景 | GC 算法 | 标记清除算法 | 复制算法 | 标记压缩算法 )

简介: Android 内存优化】垃圾回收算法 ( 内存优化总结 | 常见的内存泄漏场景 | GC 算法 | 标记清除算法 | 复制算法 | 标记压缩算法 )

文章目录

一、 内存优化总结

二、 常见的内存泄漏场景

三、 内存回收算法

四、 标记-清除算法 ( mark-sweep )

五、 复制算法

六、 标记-压缩算法





一、 内存优化总结


内存泄漏原理 : 长生命周期对象 , 持有短生命周期对象的引用 , 并且是强引用持有 , GC 无法释放该短生命周期对象引用 , 造成 OOM ;


Android Profiler 工具参考官方文档 : 使用 Memory Profiler 查看 Java 堆和内存分配



使用 Memory Analyzer ( MAT ) 内存分析工具分析内存快照 , 首先要将内存快照文件 , 转化成 MAT 工具能识别的文件 , 然后使用 MAT 工具进行分析 ;



在博客 【Android 内存优化】Android Profiler 工具常用功能 ( 监测内存 | 内存快照 ) 中保存了内存快照文件 memory-20200625T145636.hprof , 要使用 MAT 工具分析该内存快照 , 需要先将该文件转换成为 MAT 标准的文件格式 ;



在博客 【Android 内存优化】使用 Memory Analyzer ( MAT ) 工具分析内存 ( hprof 文件转换 | MAT 工具下载 | MAT 工具使用 ) 中转换了 MAT 格式的内存快照 , 下载 Memory Analyzer ( MAT ) 内存分析工具 , 并在该工具中加载了 MAT 格式的文件 ;



在博客 【Android 内存优化】使用 Memory Analyzer ( MAT ) 工具分析内存 ( MAT 工具使用 | 最大对象 | 类实例个数 | 引用与被引用 | GC Roots 最短链 ) 中 使用 Memory Analyzer ( MAT ) 内存分析工具 中分析内存快照 , 主要是查看 GC Roots 最短链 , 分析出在哪个类中引用了该对象 ;






二、 常见的内存泄漏场景


内存泄漏的常见原因 :


集合的使用

静态成员

常量

单例模式 : 不要在单例中随便持有 Context , Activity 之类的成员 , 有极大的内存泄漏隐患 ;

没有释放或关闭的资源 : 如 IO 流 , Socket 等 ;

线程 : 界面退出 , 线程没有退出 , 线程持有的引用就泄漏了 ; 尽量在其中使用弱引用 ;

Handler : 非静态内部类造成内存泄漏 ;





三、 内存回收算法


1. 内存抖动 : 应用对象的内存 , 频繁的分配 , 回收 , 造成内存使用量上下抖动 , UI 卡顿 , 严重时甚至造成 OOM ( OutOfMemoryError ) , 造成内存溢出 ;



2. 内存抖动造成溢出原因 : 对象频繁分配 , 回收 , 会大量造成内存的空隙 , 这些空隙很小无法分配大块内存 , 当整个内存都是这种空隙时 , 无法为大块内存分配空间 , 就造成了 OOM 异常 ;



3. GC 垃圾回收之前 , 需要对内存对象进行采集 , 不同的虚拟机使用不同的垃圾回收算法 , 常用的垃圾回收算法 :


标记-清除算法 ( mark-sweep )

复制算法

标记-压缩算法

分代收集算法





四、 标记-清除算法 ( mark-sweep )


标记-清除算法 ( mark-sweep ) : 步骤分为两步 : ① 标记 , ② 清除 ;



内存中分为如下几块 :


可回收对象

存活对象

可用内存


标记-清除算法 ( mark-sweep ) 算法中 , 首先标记出可回收对象 , 标记完成之后 , 统一回收 ;


回收完毕后 , 存活的对象仍然保持在原来的位置 , 可用内存基本支离破碎 , 这样就会造成内存碎片 , 这些内存碎片中无法申请大块内存 ;


image.png


上图中的内存中 , 有 24 个格子的空闲内存 , 如果要申请 5 55 个单位格子的内存 , 发现无法申请 , 没有连续 5 个格子的内存 , 此时直接出现 OOM ;


有很多内存, 但都是支离破碎的 , 没有大块内存 ;






五、 复制算法


1. 复制算法 : 将可用内存 , 分为两个想等于内存区域块 , 区域 1 11 和 区域 2 22 , 使用时只使用其中的一个区域 ;


垃圾回收前 , 只使用区域 1 11 的内存

垃圾回收后 , 将区域 1 11 的内存中可用对象复制到区域 2 22

复制时的可用对象在区域 2 22 紧密排列 , 不留空隙

这样区域 2 22 中可用内存区域是大块完整的内存 , 不会产生内存碎片


当前使用区域 1 11 的内存区域内存不足时 , 会触发上述操作 , 将当前区域 1 11 的存活对象 , 拷贝到区域 2 22 中 , 然后清理区域 1 11 内存 ;


分配回收内存时 , 只需要按照顺序移动堆指针即可 , 不考虑碎片化等问题 , 简单 , 高效 ;




2. 弊端 :



该垃圾回收算法缺陷也很明显 , 就是会浪费一半内存空间 ;


有些对象的声明周期等同于应用声明周期 , 如 Android 中的 Application 等 , 该内存对象根本不释放 , 持续往返复制这类长生存期的对象 , 会极大降低效率 ;




image.png




六、 标记-压缩算法


1. 标记压缩算法 : 与标记清除算法都需要先进行标记 ;



2. 标记压缩算法流程 :


首先标记可回收对象

然后回收这些对象

最后整理存活对象 , 将其拷贝到一块连续内存中


该方法没有复制算法浪费一半内存的问题 ;


该方法因为多了一个压缩过程 , 因此有额外的开销 ;

image.png


目录
相关文章
|
1月前
|
存储 算法 Java
理解JVM的内存模型和垃圾回收算法
理解JVM的内存模型和垃圾回收算法
27 2
|
2天前
|
算法 Android开发
安卓逆向 -- 自吐算法(3DES和AES)
安卓逆向 -- 自吐算法(3DES和AES)
8 1
|
2天前
|
算法 Java Android开发
安卓逆向 -- NDK开发实现MD5算法
安卓逆向 -- NDK开发实现MD5算法
8 0
|
2天前
|
算法 安全 JavaScript
安卓逆向 -- 算法基础(SHA)
安卓逆向 -- 算法基础(SHA)
5 0
|
2天前
|
算法 JavaScript Java
安卓逆向 -- 算法基础(数字签名)
安卓逆向 -- 算法基础(数字签名)
7 1
|
2天前
|
算法 Android开发
安卓逆向 -- 自吐算法(MAC)
安卓逆向 -- 自吐算法(MAC)
7 1
|
2天前
|
机器学习/深度学习 数据采集 监控
基于yolov2深度学习网络的车辆检测算法matlab仿真,包括白天场景和夜晚场景
基于yolov2深度学习网络的车辆检测算法matlab仿真,包括白天场景和夜晚场景
|
2天前
|
监控 Java 编译器
优化Go语言程序中的内存使用与垃圾回收性能
【2月更文挑战第5天】本文旨在探讨如何优化Go语言程序中的内存使用和垃圾回收性能。我们将深入了解内存分配策略、垃圾回收机制,并提供一系列实用的优化技巧和建议,帮助开发者更有效地管理内存,减少垃圾回收的开销,从而提升Go程序的性能。
|
5天前
|
移动开发 算法 安全
安卓逆向 -- 算法基础(Base64与HEX)
安卓逆向 -- 算法基础(Base64与HEX)
8 1
|
5天前
|
算法 JavaScript Java
安卓逆向 -- 算法基础(MAC)
安卓逆向 -- 算法基础(MAC)
6 1

热门文章

最新文章

相关产品

  • 云迁移中心