Android---GC回收机制与分代回收策略

2023-10-04 17:46

本文主要是介绍Android---GC回收机制与分代回收策略,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

GC 回收机制

垃圾回收(Garbage Collection, GC)

垃圾回收算法

JVM 分代回收策略

1. 新生代

2. 老年代 

GC Log 分析

引用


GC 回收机制

垃圾回收(Garbage Collection, GC)

垃圾就是内存中已经没有用的对象,JVM 中的垃圾回收器(Garbage Collector)会自动回收,Java 虚拟中使用“可达性分析”算法来决定对象是否可以被回收。如下图:

以 GC Root 作为起始点, 从这些节点开始向下搜索,所走过的路径称为引用链,最后通过判断对象的引用链是否可达来决定对象是否可以被回收。例如,上图中对象 A, B, C, D, E 与 GC Root 之间都存在一条直接或间接的引用链,这也代表他们与 GC Root 之间是可达的,因此它们是不能被 GC 回收掉的。而对象 M, K 虽然被对象 J 引用到,但是并不存在一条引用链连接 GC Root,所以 GC 回收时,只要遍历到 J, K, M 这三个对象,就会将它们回收。

在 Java 中,有以下几种对象可以作为 GC Root

1. Java 虚拟机栈(局部变量表)中引用的对象;

2. 方法区中静态引用指向的对象;

3. 仍处于存活状态中的线程对象;

4. Native 方法中 JNI 引用的对象;

垃圾回收算法

1. 标记清除算法(Mark and Sweep GC)

从 “GC Roots” 集合开始,将内存整个遍历一次,保留所有可以被 GC Roots 直接或间接引用到的对象,而剩下的对象都当作垃圾并回收。

过程分两步:

\bullet Mark 标记阶段:找到内存中所有的 GC Root 对象,只要和 GC Root 直接或间接相连则标记为灰色(存活对象),否则标记为黑色(垃圾对象);

\bullet Sweep 清除阶段:遍历完所有的 GC Root 之后,则将标记为垃圾的对象直接删除。

优点:实现简单,不需要将对象进行移动;

缺点:需要中断进程内其它组件的执行(即,Stop the world),并且可能产生内存碎片,提高了垃圾回收的频率。 

2. 复制算法(Copying)

将现有的内存空间分为两块,每次只使用其中一块。在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的对象,交换两个内存的角色,完成垃圾回收。

优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片;

缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。

3. 标记-压缩算法(Mark-Compact)

需要先从根节点开始对所有可达对象做一次标记,之后并不简单的清除未标记的对象,而是将所有的存活对象压缩到内存的一端,最后清理边界外所有的空间。

过程分两步:

\bullet Mark 标记阶段:找到内存中所有的 GC Root 对象,只要和 GC Root 直接或间接相连则标记为灰色(存活对象),否则标记为黑色(垃圾对象);

\bullet Compact 压缩阶段:将剩余存活对象按顺序压缩到内存的某一端。

优点:即避免了碎片的产生,又不需要两块相同的内存空间,其性价比比较高;

缺点:所谓压缩操作,仍需要进行局部对象移动,一定程度上还是降低了效率。 

JVM 分代回收策略

Java 虚拟机根据对象存活的周期不同,把堆内存划分为新生代老年代,这就是 JVM 的内存分代策略。

1. 新生代

新生成的对象优先存放在新时代中,存活率很低。新生代中,常规的一次 GC  一般可以回收 70%~ 90% 的空间,回收率很高。所有,在新时代中采用的GC 回收算法是复制算法

新生代细分为3个部分:Eden, Survivor0(简称 S0), Survivor1(简称 S1),这三部分按照 8 : 1 : 1的比例来划分新生代。

2. 老年代 

一个对象如果在新生代存活了足够长的时间(15次 GC 后仍存活)而没有被清理掉,则会被复制到老年代。老年代的内存大小一般比新生代大,能存放更多的对象。如果对象比较大(如长字符串或者大数组),并且新生代的剩余空间不足,则这个大对象会直接被分配到老年代。可以使用 

-XX:PretenureSizeThreshold

来控制直接升入老年代的对象大小。因为对象的生命周期较长,不需要过多的复制操作,所以一般采用标记压缩的回收算法。

GC Log 分析

为了让上层应用开发人员更加方便的调试 Java 程序,JVM 提供了相应的 GC 日志。在 GC 执行垃圾回收事件的过程中,会有各种相应的 log 被打印出来。其中新生代和老年代所打印的日志是有区别的:

\bullet 新生代 GC:

这一区域的 GC 叫做 Minor GC。因为 Java 对象大多都具备朝生夕灭的特性,所以 Minor GC 非常频繁,一般回收速度也比较块。

\bullet 老年代 GC:

发生在这一区域的 GC 也叫做 Major GC 或者 Full GC。当出现 Major GC,经常会伴随至少一次的 Minor GC。

引用

通过 GC Roots 的引用可达性来判断对象是否存活。

JVM 中的引用关系根据引用强度的由强到弱,可分为:

强引用(Strong Reference)

软引用(Soft Reference)

弱引用(Weak Reference)

虚引用(Phantom Reference)

这篇关于Android---GC回收机制与分代回收策略的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

SpringBoot如何通过Map实现策略模式

《SpringBoot如何通过Map实现策略模式》策略模式是一种行为设计模式,它允许在运行时选择算法的行为,在Spring框架中,我们可以利用@Resource注解和Map集合来优雅地实现策略模式,这... 目录前言底层机制解析Spring的集合类型自动装配@Resource注解的行为实现原理使用直接使用M

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Nginx之upstream被动式重试机制的实现

《Nginx之upstream被动式重试机制的实现》本文主要介绍了Nginx之upstream被动式重试机制的实现,可以通过proxy_next_upstream来自定义配置,具有一定的参考价值,感兴... 目录默认错误选择定义错误指令配置proxy_next_upstreamproxy_next_upst

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问