Java回收垃圾的基本过程与常用算法

news2024/9/22 1:25:24

目录

一、基本概述

二、垃圾分类

基本背景

举例说明各种引用类型的作用

强引用(Strong Reference)

软引用(Soft Reference)

弱引用(Weak Reference)

虚引用(Phantom Reference)

三、垃圾查找

查找垃圾时机

查找垃圾操作

四、垃圾清理

常用算法介绍

标记-清除(Mark-Sweep)

标记-复制(Mark-Copy)

标记-整理(Mark-Compact)

分代收集算法

问题背景

分代区域描述

分代垃圾回收算法执行过程

参考文献、书籍及链接


一、基本概述

当 Java 程序运行时,对象会被动态地分配在堆内存中。随着程序的运行,有些对象可能不再被引用,成为垃圾。垃圾回收是指在程序运行时,对这些垃圾对象进行清理,以便腾出内存空间供新的对象使用。

Java 垃圾回收的基本过程可以分为以下三个步骤:

  1. 垃圾分类(Garbage Classification):垃圾回收器首先需要确定哪些对象是垃圾对象,哪些对象是存活对象。一般情况下,垃圾回收器会从堆的根节点(如程序计数器、虚拟机栈、本地方法栈和方法区中的类静态属性等)开始遍历对象图,标记所有可以到达的对象为存活对象,未被标记的对象则被认为是垃圾对象。
  2. 垃圾查找(Garbage Tracing):垃圾回收器需要查找出所有垃圾对象,以便进行清理。垃圾查找的方式不同,会导致不同的垃圾回收算法。常见的垃圾查找算法有标记-清除算法、复制算法、标记-整理算法、分代算法等。
  3. 垃圾清理(Garbage Collection):垃圾回收器需要将所有的垃圾对象进行清理。垃圾清理的方式也不同,常见的有标记-清除算法、复制算法、标记-整理算法、分代算法等。垃圾清理可能会引起应用程序的暂停,不同的垃圾回收器通过不同的方式来减少这种暂停时间,从而提高应用程序的性能和可靠性。

需要注意的是,不同的垃圾回收器在执行垃圾回收时,可能会采用不同的算法和策略,因此对于不同的应用场景,需要选择合适的垃圾回收器,并对其进行适当的参数调优,以达到最优的垃圾回收效果。

二、垃圾分类

基本背景

垃圾分类指的是将堆中的对象分为存活对象和垃圾对象两类的过程,与强引用、软引用、弱引用、虚引用等引用类型没有直接关系。

在垃圾分类阶段,JVM会从一组根对象开始,通过对象之间的引用关系,遍历所有的对象,并将所有存活的对象进行标记。在标记过程中,对象会被打上标记,以便在垃圾回收的后续阶段进行处理。被标记的对象就是存活对象,未被标记的对象则被视为垃圾对象,可以被垃圾回收器回收。

强引用、软引用、弱引用、虚引用等引用类型是用于控制垃圾回收的过程中对对象的生命周期的。它们的作用是告诉垃圾回收器哪些对象是可以被回收的,哪些对象是不可以被回收的。

举例说明各种引用类型的作用

强引用(Strong Reference)

强引用是最常见的引用类型,也是默认的引用类型。如果一个对象具有强引用,垃圾收集器就不会回收它。当内存空间不足时,JVM 宁愿抛出 OutOfMemoryError 错误也不会回收具有强引用的对象。强引用的示例代码:

Object obj = new Object(); //强引用

软引用(Soft Reference)

软引用是用来描述一些还有用但并非必须的对象。对于软引用关联着的对象,只有在内存不足时才会被回收。软引用可以用来实现内存敏感的高速缓存,比如网页缓存、图片缓存等。软引用的示例代码:

Object obj = new Object();

SoftReference<Object> softRef = new SoftReference<>(obj); //软引用

obj = null; //obj 不再具有强引用,但仍有软引用

弱引用(Weak Reference)

弱引用是用来描述非必须对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。在垃圾收集器工作时,无论当前内存是否充足,都会回收只被弱引用关联的对象。弱引用的示例代码:

Object obj = new Object();

WeakReference<Object> weakRef = new WeakReference<>(obj); //弱引用

obj = null; //obj 不再具有强引用,只有弱引用

虚引用(Phantom Reference)

虚引用也称为幽灵引用或者幻影引用,是最弱的一种引用类型。一个持有虚引用的对象,和没有任何引用一样,随时可能被垃圾回收器回收。虚引用主要用于跟踪对象被垃圾回收的状态,当一个对象即将被回收时,虚引用会被放入一个 ReferenceQueue 中,可以通过 ReferenceQueue 获取到通知。虚引用的示例代码:

Object obj = new Object();

ReferenceQueue<Object> queue = new ReferenceQueue<>();

PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue); //虚引用

obj = null; //obj 不再具有强引用,只有虚引用

总之,通过不同的引用类型,我们可以更加灵活地控制对象的生命周期,避免过早或过晚地被垃圾回收器回收。 

三、垃圾查找

查找垃圾时机

不同的垃圾回收器,策略有所不同,以下只是列举:

  • 申请新对象空间、加载Class时申请空间不足
  • 老年代、永久代空间使用率到达了配置值(cms:CMSInitiatingOccupancyFraction=60,CMSInitiatingPermOccupancyFraction=60)
  • 调用System.gc()

查找垃圾操作

查找垃圾的方法可以分为两种:引用计数法和可达性分析法。

引用计数法:它是一种简单的垃圾收集算法,它的基本思想是给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1。当计数器为0时,就可以认为这个对象已经不再被引用,可以将其回收。然而,引用计数法无法解决循环引用的问题,即对象之间形成了环状结构,导致它们的计数器都不为0,即使它们已经不再被程序使用。

可达性分析法:它是现代垃圾收集算法的主要实现方式。它的基本思想是从一组被称为"根对象"(如:全局变量、栈、方法区)开始,通过一系列引用关系,能够到达的对象被认为是"存活"的,无法到达的对象则被认为是垃圾,需要被回收。在可达性分析中,对象之间形成的循环引用也会被正确处理,因为它们与根对象之间没有引用链相连。

四、垃圾清理

常用算法介绍

标记-清除(Mark-Sweep)

GC分为两个阶段,标记和清除

首先标记所有可回收的对象,在标记完成后统一回收所有被标记的对象。

缺点是清除后会产生不连续的内存碎片。碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得已再次触发GC。

标记-复制(Mark-Copy)

将内存按容量划分为两块,每次只使用其中一块。当这一块内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。这样使得每次都是对半个内存区回收,也不用考虑内存碎片问题,简单高效。

缺点需要两倍的内存空间。一种优化方式是使用eden和survivior区,具体步骤如下:

eden和survivior区默认内存空间占比为8:1:1,同一时间只使用eden区和其中一个survivior区。标记完成后,将存活对象复制到另一个未使用的survivior区(部分年龄过大的对象将升级到年老代)。

 这样,相比普通的两块空间的标记复制算法来说,只有10%的内存空间浪费,而这样做的原因是:大部分情况下,一次young gc后剩余的存活对象非常少

标记-整理(Mark-Compact)

标记-整理也分为两个阶段,首先标记可回收的对象,再将存活的对象都向一端移动,然后清理掉边界以外的内存。

 此方法避免标记-清除算法的碎片问题,同时也避免了复制算法的空间问题。

一般年轻代中执行GC后,会有少量的对象存活,就会选用复制算法,只要付出少量的存活对象复制成本就可以完成收集。

而年老代中因为对象存活率高,用标记复制算法时数据复制效率较低,且空间浪费较大。所以需要使用标记-清除或者标记-整理算法来进行回收。

所以通常可以先使用标记清除算法,当碎片率高时,再使用标记整理算法。

分代收集算法

问题背景

从上面对基础垃圾收集算法,都不是银弹,有各自不同的特点,不能应对所有的场景。在现代JVM中,通过大量实际场景的分析,可以发现,JVM内存中的对象,大致可以分为两大类:一类对象,他们的生命周期很短暂,比如局部变量、临时对象等。另一类对象则会存活很久,比如用户应用程序中DB长连接中的Connection对象。

上图中,纵轴为JVM内存使用情况,横轴为时间。图中可以发现,大多数对象的生命周期极短,很少有对象可以在GC后存活下来。基于此,诞生了分代思想。在JDK7中,Hotspot虚拟机主要将内存分为三大块,新生代(Young Genaration)、老年代(Old Generation)、永久代(Permanent Generation)

分代区域描述

主要基本区域归类分析如下:

新生代:新生代主要分为两个部分:Eden区和Survivor区,其中Survivor区又可以分为两个部分,S0和S1。该区域中,相对于老年代空间较小,对象的生存周期短,GC频繁。因此在该区域通常使用标记复制算法。

老年代:老年代整体空间较大,对象的生命周期长,存活率高,回收不频繁。因此更适合标记整理算法。

永久代:永久代又称为方法区,存储着类和接口的元信息以及interned的字符串信息。在JDK8中被元空间取代。

元空间:JDK8以后引入,方法区也存在于元空间。

分代垃圾回收算法执行过程

  • 初始态:对象分配在Eden区,S0、S1区几乎为空。

  • 随着程序的运行,越来越多的对象被分配在Eden区。

  • 当Eden放不下时,就会发生MinorGC(即YoungGC),此时,会先标识出不可达的垃圾对象,然后将可达的对象移动到S0区,并将不可达的对象清理掉。这时候,Eden区就是空的了。在这个过程中,使用了标记清理算法及标记复制算法。

  • 随着Eden放不下时,会再次触发minorGC,和上一步一样,先标记。这个时候,Eden和S0区可能都有垃圾对象了,而S1区是空的。这个时候,会直接将Eden和S0区的对象直接搬到S1区,然后将Eden与S0区的垃圾对象清理掉。经历这一轮的MinorGC后,Eden与S0区为空。

  • 随着程序的运行,Eden空间会被分配殆尽,这时会重复刚才MinorGC的过程,不过此时,S0区是空的,S0和S1区域会互换,此时存活的对象会从Eden和S1区,向S0区移动。然后Eden和S1区中的垃圾会被清除,这一轮完成之后,这两个区域为空。

  • 在程序运行过程中,虽然大多数对象都会很快消亡,但仍然存在一些存活时间较长的对象,对于这些对象,在S0和S1区中反复移动,会造成一定的性能开销,降低GC的效率。因此引入了对象晋升的行为。

  • 当对象在新生代的Eden、S0、S1区域之间,每次从一个区域移动到另一个区域时,年龄都会加一,在达到一定的阈值后,如果该对象仍然存活,该对象将会晋升到老年代。

  • 如果老年代也被分配完毕后,就会出现MajorGC(即Full GC),由于老年代通常对象比较多,因此标记-整理算法的耗时较长,因此会出现STW现象,因此大多数应用都会尽量减少或着避免出现Full GC的原因。

参考文献、书籍及链接

1.JVM经典垃圾回收器的运行机制和原理-康志兴的博客 | kangzhixing Blog

2.《深入理解Java虚拟机》

3.《垃圾回收的算法与实现》

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/480496.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

广搜的优化技巧(备赛中)

A.电路维修 这道题我们对于每一个点都有四个方向&#xff0c;分别为 char op[]{"\\/\\/"}; 如果我们当前点到下一个点的方向不是对应的方向时我们的distance就加1&#xff0c;因为我们要求最优距离&#xff0c;所以我们采取一个小贪心的法则&#xff0c;每一次我们将…

「神州数码DCN」SAVI在IPV6环境下的应用

前言 介绍 ISIS&#xff0c;中间系统到中间系统的网络协议&#xff0c;最初是OSI组织为了他的CLNP&#xff08;类似于TCP/IP中的IP网络&#xff09;而设计的动态路由协议&#xff0c;后IETF对其进行修改和填充&#xff0c;现可以在TCP/IP和OSI环境中使用&#xff0c;称为&…

JavaWeb学习------jQuery

JavaWeb学习------jQuery jQuery函数库下载 jQuery函数库下载官网&#xff1a;Download jQuery | jQuery配套资料&#xff0c;免费下载 链接&#xff1a;https://pan.baidu.com/s/1aXBfItEYG4uM53u6PUEMTg 提取码&#xff1a;6c9i 然后下载&#xff1f; 来到官网&#xf…

Spark 1:Spark基础入门

Spark是什么 定义&#xff1a;Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎。 Spark 借鉴了 MapReduce 思想发展而来&#xff0c;保留了其分布式并行计算的优点并改进了其明显的缺陷。让中间数据存…

Winform从入门到精通(36)—ColorDialog(史上最全)

文章目录 前言一、属性1、AllowFullOpen2、AnyColor3、Color4、FullOpen5、ShowHelp6、SolidColorOnly7、Tag二、事件1、HelpRequest前言 当我们需要设置某个控件的颜色时,并且需要弹出一个可以选择颜色的对话框时,这时候就需要使用ColorDialog 一、属性 1、AllowFullOpen…

详解正则化

&#xff08;一&#xff09;正则化目的 防止过拟合现象&#xff0c;通过降低模型在训练集上的精度来提高其泛化能力&#xff0c;从而增加正则项 常见的降低过拟合方法 ■增加数据集的数据个数。数据量太小时&#xff0c;非常容易过拟合&#xff0c;因为 小数据集很容易精确拟…

Linux线程相关函数:线程的创建、回收、退出、取消

1. 线程号 进程号在系统中唯一&#xff0c;但线程号只在其所属进程环境中有效。 &#xff08;1&#xff09;pthread_self函数 #include<pthread.h>pthread_t pthread_self(void); /* 功能&#xff1a;获取线程号 返回值&#xff1a;调用此函数线程的ID */ pthread_se…

基于ssm的论坛系统的设计与实现【附源码】

基于ssm的论坛系统的设计与实现 摘 要 早期的网络论坛系统已经诞生一段时间&#xff0c;随着互联网技术的发展&#xff0c;它已经从最初的简单电子公告板系统变成了一种丰富的论坛系统社区模型。人们通过论坛系统进行信息的获取、发布和交流已经成为一种普遍的社交方式&#x…

一键开关机电路

一键开关机电路&#xff0c;通常用在防止关机导致数据保存发生错误&#xff0c;特别是在写EEPROM&#xff0c;FLASH和SD卡时&#xff0c;如果正在写入数据时断电&#xff0c;可能会导致数据保存错误&#xff0c;甚至导致元件损坏。一键开关机电路是由CPU来掌控&#xff0c;决定…

零基础带你认识HTML常用标签

目录 HTML 结构认识 HTML 标签HTML 文件基本结构标签层次结构快速生成代码框架 HTML 常见标签注释标签标题标签&#xff1a;h1 - h6水平线 hr 标签段落标签: p换行标签: br格式化标签图片标签: imgimg 标签的其他属性 超链接标签: a 表格标签基本使用和并单元格 列表标签表单标…

Compiler Lab1- 自制词法分析器

由于编译原理课的Lab1为自制词法分析器&#xff0c;所以笔者用C实现了一个极简的C语言词法分析器&#xff0c;用于分析C语言源代码。它可以处理关键字、标识符、整数、实数、浮点数的科学计数法表示、运算符、分隔符、字符串字面量、字符字面量、注释和预处理指令。请注意&…

【五一创作】力扣刷题实录(大厂用题)—— 1. 打家劫舍

1. 打家劫舍 某大厂 2022 年 9 月面试题挑战&#xff08;三&#xff09; 1.1 题目描述 力扣真题地址&#xff1a;https://leetcode.cn/problems/house-robber/?envTypestudy-plan-v2 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;…

Photoshop如何使用路径与矢量工具之实例演示?

文章目录 0.引言1.制作名片2.利用钢笔工具抠出复杂图像3.制作App图标4.制作软件登录界面5.将图片切成九宫格 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及其配套素材结合网上相关资料进行学习笔记总结…

简单搭建node后台(笔记用)

毕设过程 mongodb 配置 使用node写后台一些语法运用bug关于安装一款群控软件后&#xff0c;修改了环境变量导致后台崩溃![](https://img-blog.csdnimg.cn/7c684b2e318048b3ad1db78484e10e6a.jpeg) vue管理后台 mongodb 配置 https://blog.csdn.net/weixin_43405300/article/de…

Unity API详解——Vector3类

Vector3类是用于表示三维向量的类&#xff0c;其中的x、y和z成员表示向量在三个轴上的分量。Vector3类还包含许多常用的函数&#xff0c;例如计算向量长度、向量点积和向量叉积等等。此外&#xff0c;Vector3类还具有许多方便的操作&#xff0c;例如规范化向量、向量加法、向量…

数据预处理--sort乱序DICOM文件

我们直接从PACS系统里拷贝下来的图像&#xff0c;很多情况下是乱序的&#xff0c;随机命名的。如下图 从这个文件夹名字&#xff0c;我们只知道患者的 ID 信息&#xff0c;不知道这个图像是什么模态&#xff08;CT/MRI/Xray&#xff09;&#xff0c;也不知道扫的是哪个部位&…

【电子学会】2023年03月图形化一级 -- 甲壳虫走迷宫

甲壳虫走迷宫 1. 准备工作 &#xff08;1&#xff09;绘制如图所示迷宫背景图&#xff0c;入口在左下角&#xff0c;出口在右上角&#xff0c;线段的颜色为黑色&#xff1b; &#xff08;2&#xff09;删除默认小猫角色&#xff0c;添加角色&#xff1a;Beetle&#xff1b; …

Python探索性P图,四种增强方式快速玩转pillow库

嗨害大家好鸭&#xff01;我是爱摸鱼的芝士❤ 我们平时使用一些图像处理软件时&#xff0c; 经常会看到其对图像的亮度、对比度、色度或者锐度进行调整。 你是不是觉得这种技术的底层实现很高大上&#xff1f; 其实最基础的实现原理&#xff0c; 用 Python 实现只需要几行…

【力扣周赛】第343场周赛

【力扣周赛】第343场周赛 2660&#xff1a;保龄球游戏的获胜者题目描述解题思路 2661&#xff1a;找出叠涂元素题目描述解题思路 2660&#xff1a;保龄球游戏的获胜者 题目描述 描述&#xff1a;给你两个下标从 0 开始的整数数组 player1 和 player2 &#xff0c;分别表示玩家…

系统集成项目管理工程师 笔记(第10章 项目质量管理)

文章目录 10.1.2 质量管理及其 发展史 35610.1.3 项目质量管理 35810.2.2 规划质量管理的输入 35910.2.3 规划质量管理的工具与技术 3601、成本效益分析法2、质量成本法&#xff08;一致性成本【预防、评价】 和 非一致性成本【内部、外部】&#xff09;3、七种基本质量工具&am…