JVM(5)

news2024/11/25 8:21:08

垃圾回收相关

垃圾收集器

警告:纯八股文!

如果说上面我们讲的收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体体现.

垃圾收集器的作用:垃圾收集器是为了保证程序能够正常,持久运行的一种技术,它是将程序中不用的死亡对象也就是垃圾对象进行清除,从而保证新的对象能够正常申请到内存空间.

垃圾回收器和垃圾回收算法的关系:

垃圾回收器是一种负责自动管理内存的软件组件,它负责在程序运行时识别和回收不再使用的内存(即垃圾),以便将内存重新分配给程序的其他部分.垃圾回收器实现了垃圾回收算法,这些算法决定了如何识别和回收垃圾.

1.垃圾回收器是实现垃圾回收算法的具体实体或组件,它是负责执行垃圾回收算法的执行者.

2.垃圾回收算法是一组规则和策略.用于确定哪些内存被视为垃圾,并在何时回收这些内存.

3.垃圾回收器通过调用和执行垃圾回收算法来实现内存管理.它负责在适当时机进行垃圾回收.并选择适当回收垃圾回收算法来回收内存.不同的垃圾处理器能实现不同的垃圾回收算法,以满足不同场景的需求.

以下这些收集器是HotSpot虚拟机伴随着不同版本推出的重要的垃圾收集器:

上图展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用. 所处的区域,表示它是属于新生代收集器还是老年代收集器.再讲具体的收集器之前我们先来明确三个概念:

并行:指多条垃圾收集线程并行工作,用户线程仍处于等待状态.

并发:指用户线程和垃圾回收线程同时执行(不一定并行,可能会交替执行),用户程序继续执行,而垃圾收集程序在另外一个CPU上.

吞吐量:就是CPU用于运行用户代码的时间与CPU总消耗时间的比值.

吞吐量=运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)

例如:虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那么吞吐量就是99%.

为什么会有这么多的垃圾收集器?

JVM有多种垃圾收集器,是因为不同的应用场景和需求可能需要不同的垃圾回收算法和策略.这些垃圾回收器的存在是为了在不同情况下提供最佳性能和吞吐量,并满足应用程序要求.

1.应用场景多样化:不同类型的应用程序具有不同的内存使用模式和性能要求.例如,一些应用可能需要低延迟,而另一些应用可能更注重吞吐量.因此需要不同类型的垃圾收集器来满足需求.

2.内存使用模式的不同:一些应用程序可能会生成大量短期对象,不同的垃圾收集器能针对这些不同的内存使用方式优化.

3.硬件和操作系统的不同:不同的硬件平台和操作系统可能对垃圾收集器产生不同的影响.因此存在多种垃圾回收器可以在不同的硬件和操作系统环境下提供最佳的性能.

4.持续的研究,更进,历史发展:自从有了Java语言就有了垃圾收集器,这么多垃圾收集器其实是历史发展的产物.最早的垃圾回收器为Serial,也就是串行执行的垃圾收集器,Serial Old为串行的老年代收集器,而随着时间的发展,为了提升更高的性能,于是就有了Serial多线程版的垃圾回收器ParNew.后来人们想要更高吞吐量的垃圾收集器,吞吐量是指单位时间内成功回收垃圾的数量,于是就有了吞吐量优先的垃圾收集器Parallel Scavenge(吞吐量优先的新生代垃圾收集器)和Parallel Old(吞吐量优先的老年代垃圾收集器).随着技术的发展后来又有了CMS垃圾收集器,CMS可以兼顾吞吐量和以获取最短回收停顿时间为目标的收集器,在JDK1.8(包含)之前BS系统的主流垃圾收集器,而在JDK1.8之后,出现了第一个既不完全属于新生代也不完全属于老年代的垃圾收集器G1,G1提供了基本不需要停止程序就可以收集垃圾的技术.

下面我们来看每种垃圾收集器的具体介绍:

CMS收集器(老年代收集器,并发GC)

特性:CMS收集器是一种以获取最短回收停顿时间为目标的收集器.目前很大一部分的Java应用几种在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,给用户带来较好的体验.CMS收集器就非常符合这类应用的需求.

CMS收集器是基于"标记-清除"算法实现的,它的运作过程较为复杂,整个过程分为四个步骤:

初始标记:初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要"Stop the world".("Stop the world"是指在垃圾收集的过程当中,应用程序的所有线程都会停止执行,这样垃圾收集器可以独占地执行垃圾收集操作.在停止的过程中,所有的用户线程都会暂停,包括应用程序的业务逻辑和其它的并发操作.这种暂停时间是可预测的,但是会对系统的响应时间和吞吐量产生影响.)

并发标记:并发标记阶段就是进行Roots Tracing的过程.

重新标记:重新标记阶段是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象标记记录,这个阶段的停顿时间一般会比初始标记阶段稍微长一些,但远比并发标记的时间短,仍然需要"Stop the world".

并发清除:并发清除阶段会清除对象.

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程可以与用户线程一起工作,所以,从整体上来说,CMS收集器的内存回收过程是与用户线程一起并发执行的.

优点:

CMS是一款优秀的收集器,它的主要优点在名字上已经体现出来了:并发收集,低停顿 

缺点:

CMS收集器对CPU资源非常敏感. 其实,面向并发设计的程序都对CPU资源比较敏感.在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者CPU资源)而导致应用程序变慢,总吞吐量会降低.  CMS默认启动的回收线程数是(CPU数量+3)/4.也就是当CPU在4个以上时,并发回收时垃圾收集线程不少于25%的CPU资源.并且随着CPU数量的增加而下降.但是当CPU不足4个(譬如2个)时,CMS对用户程序的影响就可能变得很大.

CMS收集器无法处理浮动垃圾,可能会出现"Concurrent Mode Failure"失败而导致另一次Full GC的产生.由于CMS并发清理阶段用户线程还在运行着,伴随程序运行字眼就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC再清理掉. 这一部分就叫做"浮动垃圾".也是由于在垃圾回收阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用.要是CMS运行期间预留的内存无法满足程序需要,就会出现一次"Concurrent Mode failure"失败,这是虚拟机将启动后备预案:临时启动Serial Old收集器来重新进行老年代的垃圾收集,这样停顿的时间就很长了.

CMS收集器会产生大量空间碎片

CMS是一款基于"标记-清除"算法实现的收集器,这意味着收集结束时会有大量空间碎片的产生.空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC.

G1收集器(唯一一款全区域的垃圾回收器)

G1垃圾收集器是用在heap memory很大的情况下, 把heap划分为很多很多的region 块, 然后并行的对其进行垃圾回收.

G1垃圾收集器在清除实例所占用的内存空间后,还会做内存压缩.

G1垃圾收集器回收region的时候基本不会STW,而是基于most garbage优先回收(整体来看是基于"标记-整理"算法, 从局部(两个region之间)基于"复制"算法)的策略来对region进行垃圾回收的.无论如何,G1收集器采用的算法都意味着一个region有可能属于Eden,Survivor或者Tenured内存区域.图中的E表示改region属于Eden内存区域,S属于Survivor内存区域,T属于Tenured内存区域.图中空白的表示未使用的内存空间.G1垃圾收集器还增加了一种新的内存区域,叫做Humongous内存区域,如图中的H块.这种内存区域主要用于存储大的对象-即大小超过一个region大小的50%对象.

 

年轻代垃圾收集

在G1垃圾收集器中,年轻代的垃圾回收过程使用复制算法,把Eden区和Survivor区的对象复制到新的Survivor区域.

如下图:

 

老年代垃圾收集

对于老年代上的垃圾收集,G1垃圾收集器也分为4个阶段,基本跟CMS垃圾收集器一样,但略有不同.

初始标记阶段-同CMS垃圾收集器的初始标记阶段一样,G1也需要暂停应用程序的执行,它会标记从根对象出发,在根对象的第一层孩子节点中标记所有可达的对象.但是G1的垃圾收集器的初始标记是跟minor gc一同发生的. 也就是说,在G1中,你不用像CMS那样,单独暂停应用程序来进行初始标记阶段,而是在G1触发minor gc的时候一并将老年代的初始标记给做了 

并发标记阶段-在这个阶段G1做的事情跟CMS一样.但G1同时还做了一件事情,就是如果在并发标记阶段中,发现哪些Tenured region中对象的存活率很小或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,而不用等到后面的clean up阶段.这也是Garbage First名字的由来.同时,在该阶段,G1会计算每个region的对象存活率,方便后面的clean up阶段使用.

最终标记-在这个阶段G1做的事情和CMS一样,但是采用的算法不同,G1采用一种叫STAB的算法能够在Remark阶段更快的标记可达对象.

筛选回收阶段-在G1中,没有CMS中对应的Sweep阶段.相反它有一个Clean up/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进行回收,这个阶段也是与minor gc一同发生的,如下图所示:

G1是一款面向服务端应用的垃圾收集器.HotSpot开发团队赋予它的使命是未来可以替换掉JDK1.5中发布的CMS收集器.如果你的应用追求低停顿,G1可以作为选择;如果你的应用追求吞吐量,G1并不带来明显的好处.

总结:一个对象的一生

 一个对象的一生:我是个普通的Java对象,我出生在Eden区,在Eden区我还看到了和我长得很像的小兄弟,我们在Eden区中玩了挺长时间.有一天Eden区的人实在是太多了,我就被迫去了Survivor区的"From"区(s0区),有时候在Survivor的"To"区(s1区),居无定所.知道我18岁的时候,爸爸说我成人了,该去社会上闯闯了.于是我去了老年代那边,老年代里,人很多,并且年龄都挺大的,我在这里也认识了很多人.在老年代里,我生活了很多年(每次GC加一岁)然后被回收了.

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

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

相关文章

【 C++ 】空间配置器

1、什么是空间配置器 空间配置器,顾名思义就是为各个容器高效的管理空间(空间的申请与回收)的,在默默地工作。虽然在常规使用STL时,可能用不到它,但站在学习研究的角度,学习它的实现原理对我们有很大的帮助。 2、为什…

P4715 【深基16.例1】淘汰赛题解

题目 有(n≤7)个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1号国家和2号国家踢一场比赛,胜者晋级。3号国家和4号国家也踢一场,…

zephyr学习

zephyr内核对象学习 定时器 类似linux的定时器, 可以分别设置第一次到期时间和后续的周期触发时间, 可以注册到期回调和停止回调 还有一个计数状态,用于标记timer到期了多少次 duration:设定timer第一次到期的时间。 period: …

SpringBoot整合JdbcTemplate

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合JdbcTemplate 📚个人知识库: Leo知识库,欢迎大家访问 目录 …

超详细的 pytest 钩子函数 之初始钩子和引导钩子来啦

前几篇文章介绍了 pytest 点的基本使用,学完前面几篇的内容基本上就可以满足工作中编写用例和进行自动化测试的需求。从这篇文章开始会陆续给大家介绍 pytest 中的钩子函数,插件开发等等。 仔细去看过 pytest 文档的小伙伴,应该都有发现 pyt…

递归与回溯2

一:递归分治 什么是递归? 函数自己调用自己通过函数体来进行循环以自相似的方法重复进行的过程 递归的过程:先自顶向下找到递归出口,在自底向上回到最初的递归位置 推导路径未知的题目只能用递归不能用循环 比如求多叉树的节点&…

NOC2023软件创意编程(学而思赛道)python小高组初赛真题

软件创意编程 一、参赛范围 1.参赛组别:小学低年级组(1-3 年级)、小学高年级组(4-6 年级)、初中组。 2.参赛人数:1 人。 3.指导教师:1 人(可空缺)。 4.每人限参加 1 个赛项。 组别确定:以地方教育行政主管部门(教委、教育厅、教育局) 认定的选手所属学段为准。 二、…

基于原子变量的内存模型优化

概述 线程间同步通常的实现方法通常为互斥锁,但互斥锁对性能造成了影响,C11引入了内存模型,定义了STD::memory_order枚举,结合原子性操作,实现无锁线程数据同步。 关于memory_order memory_order_relaxed&#xff1…

电子电气架构——车载以太网协议栈

电子电气架构——车载以太网协议栈 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值&#xff0c…

【Java文件报错】Cannot resolve symbol ‘println‘ 【及解决】

一、问题描述 在Java源代码文件中,使用 System.out.println() 语句进行输出,编译器提示“Cannot resolve symbol ‘println’(无法解释关键字)”, println飘红。报错代码及报错截图如下所示。 import java.io.*;public class St…

【JavaSE】时间类相关API以及使用

目录 时间类相关API 1.Date类 2.SimpleDateFormat类 3.Calendar类 4.JDK8-时区,时间和格式化 5.JDK8-日历和工具类 时间类相关API 以下内容是通过观看黑马java的常见API视频总结加笔记,其中有JDK7以及以前的时间类,包括:Date&…

前后端分离Vue+nodejs酒店公寓客房预订管理系统udr7l-java-php-django-springboot

本系统的设计与实现共包含13个表:分别是关于我们信息表,配置文件信息表,公寓信息评论表信息表,公寓入住信息表,公寓退房信息表,公寓信息信息表,公寓预订信息表,系统公告信息表,收藏表…

pdf电子准考证查询下载系统(实证效果可照片)V1.0

CSDNpdf电子准考证查询下载系统(实证效果可照片)V1.0 使用场景: 教育机构比如学校用pdf准考证查询下载系统(实证效果可照片,最适合准考证打印); 也可自定义图片及坐标用于各种优秀党员三好学生等荣誉证书、聘书授权代理pdf电子证书查询与下载。 推荐Linux PHP5.5-7.3使用使…

utniy urp shinyssrr插件使用

文章目录 前言步骤1首先在URP的配置文件里添加SSR后处理2 修改RenderingPath为延迟渲染3 启用深度纹理4 为物体添加脚本 注意事项插件下载 前言 用来实现屏幕空间反射效果 unity 版本为2021.3.8LTS,低版本的untiy URP的参数设置位置z可能会不同 步骤 1首先在URP的…

Spring对IoC的实现

个人名片: 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:🖼️…

多态——细致讲解

🔶多态基础概念  🔶概念   🔱多态性   🔱多态——重新(覆盖)  🔶示例   🔶基本使用方法   🔶特例    🔱协变    🔱析构函数重写  🔱多态原理…

链表OJ刷题(二)

制作不易,三连支持一下呗!!! 文章目录 前言一、链表的回文结构二、相交链表三、链表中倒数第k个节点四、环形链表Ⅰ和Ⅱ总结 前言 一、链表的回文结构 链表的回文结构_牛客题霸_牛客网 这里我们需要先了解一下什么叫做回文&#…

测开新手:pytest+requests+allure自动化测试接入Jenkins学习

最近在这整理知识,发现在pytest的知识文档缺少系统性,这里整理一下,方便后续回忆。 在python中,大家比较熟悉的两个框架是unittest和pytest: Unittest是Python标准库中自带的单元测试框架,Unittest有时候…

基于python+django+mysql在线点餐订餐外卖系统设计与实现 开题报告参考

博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

排序(3)——直接选择排序

目录 直接选择排序 基本思想 整体思路(升序) 单趟 多趟 代码实现 特性总结 直接选择排序 基本思想 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的…