垃圾收集器

2023-09-15 15:06:18

1.前言

        结合之前介绍的垃圾回收算法,算法只是我们将无效对象回收的一种方式,最终将这些算法运用起来的,是垃圾收集器,随着java应用的业务场景越来越多,java在不停的版本迭代过程中,推出了很多种垃圾收集器,来应对不同的业务以及服务场景。

2.七种垃圾收集器

2.1Serial 收集器(新生代)

概述:Serial(串行)收集器是最基本、历史最悠久的垃圾收集器,采用“标记-复制”算法负责新生代的垃圾收集。它是Hotspot虚拟机运行在客户端模式下的默认新生代收集器。

线程:它是一个单线程收集器。它会使用一条垃圾收集线程去完成垃圾收集工作,并且它在进行垃圾收集工作的时候,必须暂停其他所有的工作线程( "Stop The World" ),直到收集结束。

注意:Stop The World就是全线暂停简称STM。想象一下,我们在GC过程中,如果其他用户线程仍然持续运行,那么除了已经存在的垃圾对象,会有新的垃圾对象产生,想要在程序运行的过程中,去彻底的回收所有垃圾,几乎是不太可能的,所以GC收集器就产生了这样的一个动作,就是先将应用的其他线程都挂起,全量去进行GC操作,操作完毕之后释放,这个动作就是我们提到的Stop The World,这个动作的重要性其实是,在这段时间里我们程序的其他的操作都无法进行,在某些场景还可以接受,对于一些特殊场景,延迟低是必须的,这对于我们的停顿时间的要求是非常高的,所以在越来越新版本的GC收集器中,对于时间的管理,都会有不同的做法。

优点:Serial收集是简单而高效的 。在单个 CPU 环境下,由于没有线程交互的开销,因此拥有最高的单线程收集效率

2.2. Serial Old 收集器(老年代)

Serial Old收集器同样是一个单线程收集器,采用“标记-整理”算法负责老年代的垃圾收集。

如果在服务器端使用,它主要有两种用途:

  1. JDK5及以前版本,与Parallel Scavenge收集器搭配使用;
  2. 作为CMS收集器发生失败时的后备预案;

注意:STM动作并不是随时暂停所有用户线程的,会选择安全点暂停。 

2.3.ParNew 收集器(新生代)

ParNew 收集器是第一个多线程的垃圾收集器。它是运行在 Server模式下的虚拟机的首要选择,可以与 Serial OldCMS 垃圾收集器一起搭配工作,采用“标记-复制”算法。

是Serial GC的升级版,明显的提升肯定是GC的时间变短,STW的时间肯定也会相应的变短。

2.4. Parallel Scavenge 收集器(新生代)

JDK1.8 默认收集器,也是一款新生代收集器,使用“标记-复制”算法实现的多线程收集器。

与其它收集器目标不同CMS等其它收集器目标是尽可能缩短垃圾收集时用户线程的停顿时间。但是Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。所谓吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值。

使用场景:停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。

2.5. Parallel Old 收集器(老年代)

是一个多线程的垃圾收集器,使用“标记-整理”算法。在注重吞吐量以及 CPU 资源的场合,都可以优先考虑 Parallel Scavenge 收集器 + Parallel Old 收集器。

2.6. CMS 收集器(老年代)

CMS(Concurrent Mark Sweep)是一种以获取最短回收停顿时间为目标的收集器,基于“标记-复制”算法实现,是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。适合低延迟的场景,保证用户的使用体验。

为什么说是基本上同时工作呢?那就需要了解CMS的工作流程了。

整个过程分为四个步骤

  • 初始标记: 暂停所有的其他线程,并记录下直接与 root相连的对象,速度很快 ;
  • 并发标记: 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。
  • 重新标记: 重新标记阶段,是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间长,远远比并发标记阶段时间短
  • 并发清除: 开启用户线程,同时 GC 线程开始对未标记的区域做清扫。

优点和缺点:

优点:并发收集低停顿

缺点:

影响用户线程的执行效率:并发标记并发清除时,是和用户线程一起运行的,收集过程中肯定占用了用户程序的CPU资源。CMS默认启动的回收线程数是(CPU数量+3)/4,当CPU数量在4个以上时,垃圾回收线程占用不少于25%的CPU资源,势必影响用户线程的执行效率。

浮动垃圾:在并发清除阶段,用户线程并没有停止,所以还会继续产生新的垃圾,只能等待下一次收集时才能进行回收,这部分垃圾被称为“浮动垃圾”。

空间碎片:因为CMS收集器是基于“标记-清除”算法实现的,所以在进行大量的垃圾回收时,会产生很多不连续的内存空间。

注意:由于垃圾收集阶段用户线程还需要持续运行,所以需要预留足够的内存空间提供给用户线程使用,因此CMS收集器不能像其它收集器那样等到老年代几乎完全被填满了再进行收集。

2.7. G1 收集器(老年代)

2.7.1.什么是G1收集器

G1 ( Garbage-First ) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器、大容量内存的机器。它不再严格按照分代思想进行垃圾回收。G1采用局部性收集的设计思路和基于Region的内存布局形式。

2.7.2.G1收集器的结构

不同于Serial系列、Parallel系列、CMS系列,它们都是基于把内存进行物理分区的形式把JVM内存分成老年代、新生代、永久代或MetaSpace,这种分区模式下进行垃圾收集时必须对某个区域进行整体性的收集(比如整个新生代、整个老年代收集或者整个堆)。然后以Region为单位自由的组合成新生代、老年代、Eden区、survior区、大对象区(Humonggous Region)

这种思想上的转变和设计,使得G1可以面向堆内存任何部分来组成回收集来进行回收,衡量标准不再是它属于哪个分代,而是哪块内存存放的垃圾最多,回收收益最大,这就是G1收集器的 Mixed GC模式,即混合GC模式。

2.7.3.G1 垃圾收集器工作流程

  • 初始标记(Initial Marking):这个阶段仅仅只是标记GC Roots能直接关联到的对象,这阶段需要停顿线程,但是耗时很短。
  • 并发标记(Concurrent Marking):从GC Roots开始对堆的对象进行可达性分析,递归扫描整个堆里的对象图,找出存活的对象,这阶段耗时较长,但是可以与用户程序并发执行。
  • 最终标记(Final Marking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后遗留记录。
  • 筛选回收(Live Data Counting and Evacuation):负责更新 Region 的统计数据,对各个 Region 的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划。可以自由选择多个Region来构成回收集,然后把回收的那一部分Region中的存活对象==>复制==>到空的Region中,最后对那些Region进行清空。

2.7.4 .G1 垃圾收集器的特点

并行与并发G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU来缩短停顿时间。 

分代收集:虽然 G1 可以不要其他收集器就能独立管理整个 GC 堆,但还是保留了分代的概念。

空间整合G1从整体来看是基于“标记-整理”算法实现的收集器,从局部(两个Region之间)上来看是基于“标记-复制”算法实现的。这意味着G1运行期间不会产生内存空间碎片,收集后能提供规整的可用内存。

用户指定期望停顿:设置不同的期望停顿时间,可以让G1在不同的场景下取得吞吐量和延迟之间的最佳平衡,G1的默认停顿目标为200毫秒。

3.总结

从现在往回看,我们会发现每个垃圾收集器都是一个时代的产物。

第一阶段:在单核CPU,内存资源稀缺的时代使用的是Serial和Serial Old收集器,对于单核CPU,内存只有几十M的场景Serial的效率是非常高的。

第二阶段:进入多核CPU时代后出现了Parallel Scavenge和Parallel Old收集器,利用多线程并行收集极大的提高了垃圾收集的效率,所以在多核CPU场景,内存在几百M到几G的场景Parallel Scavenge和Parallel Old是适用的。

第三阶段:随着内存的变大,垃圾收集的过程时间变得越来越长了,BS系统的发展也逐渐开始重视用户体验了,所以就出现了CMS以减少用户线程停顿时间为目的的收集器,CMS通过并发收集减少了用户线程的停顿时间,在多核CPU,并且内存空间几G到几十G的空间、并且注重用户体验的CMS垃圾收集器是适用的。

第四阶段:CMS遗留了一些比较致命的问题,所以就有了G1,G1不再对内存进行物理上的分代,而只是进行逻辑上的分区,通过各种机制让垃圾收集变得更智能和可控了,多核CPU,并且内存在10G到上百G的场景G1比较适合。

更多推荐

【EI会议】第二届声学,流体力学与工程国际学术会议(AFME 2023)

第二届声学,流体力学与工程国际学术会议20232ndInternationalConferenceonAcoustics,FluidMechanicsandEngineering(AFME2023)声学、流体力学两个古老的学科发展至今,无时无刻都在影响着我们的生活。小到日常使用的耳机、风扇,大到制造的轮船、飞机。时代发

学习记忆——宫殿篇——记忆宫殿——记忆桩——单间+客厅+厨房+厕所+书房+院子

文章目录单间客厅厨房厕所书房院子单间水壶水龙头香皂果汁机电视门空间花红酒葡萄不锈钢白毛沙发彩色垫子吉他皮椅挂画风扇糖抱枕盒子花土水晶腿衣柜笔三环相框水壶壁挂台灯被网球拍足球抽屉闹钟蝴蝶心斑马三轮车音响椅子碗玩偶烟灰缸电视窗帘玻璃上铺镜子壁灯枕头电话纸盘鱼长方形镜子垃圾桶电视柜地板砖折叠凳窗帘挂坠毯子竹节式台灯台灯床头床

如何利用好Twitter的功能进行营销

虽然Twitter不是最复杂的社交网络,但您需要了解其中的一些特性和功能。这些是我们进行基本操作的地方。您进行探索并想出更多有创意的方式来使用这些功能。推文。推文是您可以分享的帖子和更新,限制在140个字符内。每一条推文都有存档,您可以查看自己和其他用户的推文。通过浏览其他用户的近期推文,您可以更好地了解他们关注的话题

SpringCLoud——docker中的数据卷

数据卷容器与数据耦合的问题不便于修改当我们要改Nginx的HTML内容时,需要进入容器内部修改,很不方便。数据不可复用在容器内的修改对外是不可见的。所有修改对新的容器是不可复用的。升级维护困难数据在容器内,如果要升级容器必然删除旧容器,所有数据都跟着删除了。数据卷(Volume)是一个虚拟目录,指向宿主机文件系统中的某

MQ和分布式事务

MQmq通知时,消费者没消费到怎么办简单聊聊消息中间件?你了解那些具体的消息中间件产品?mq的消费端是怎么处理的?整理一下你的消费端的整个处理逻辑流程,然后说说你的ack是在哪里返回的。按照你这样画的话,如果数据库突然宕机,你的消息该怎么确认已经接收?那如果发送端的服务是多台部署呢?你保存消息的时候数据库就一直报唯一性

Vue中如何进行表格排序与过滤

Vue中如何进行表格排序与过滤在Vue.js中,表格是一个常见的数据展示方式。很多时候,我们需要对表格中的数据进行排序和过滤,以提供更好的用户体验。本文将介绍如何在Vue中实现表格的排序和过滤功能,并提供相关的代码示例。准备工作在开始之前,我们需要准备一些基本的工作。首先,确保你已经安装了Vue.js,并且创建了一个V

Service 层异常抛到 Controller 层处理还是直接处理?

0前言一般初学者学习编码和[错误处理]时,先知道[编程语言]有一种处理错误的形式或约定(如Java就抛异常),然后就开始用这些工具。但却忽视这问题本质:处理错误是为了写正确程序。可是1啥叫“正确”?由解决的问题决定的。问题不同,解决方案不同。如一个web接口接受用户请求,参数age,也许业务要求字段是0~150之间整数

JMeter:断言之响应断言

一、断言的定义断言用于验证取样器请求或对应的响应数据是否返回了期望的结果。可以是看成验证测试是否预期的方法。对于接口测试来说,就是测试Request/Response,断言即可以针对Request进行,也可以针对Response进行。但大部分是对Response做断言。JMeter常见的断言元件如下:1.响应断言2.J

【MySQL系列】如何在MySQL中使用触发器?MySQL触发器详解

MySQL可以通过触发器来实现自动化业务逻辑和操作。触发器是一种在数据库表发生特定操作时自动执行的存储过程,能够响应特定事件,如INSERT、UPDATE和DELETE语句。本文将详细介绍MySQL中的触发器概念、创建和使用方法,以及一些注意事项。一、概念触发器是一种与表相关联的一段代码,它会在特定事件(INSERT、

利用 SOAR 加快事件响应并加强网络安全

随着攻击面的扩大和攻击变得越来越复杂,与网络攻击者的斗争重担落在了安全运营中心(SOC)身上。SOC可以通过利用安全编排、自动化和响应(SOAR)平台来加强组织的安全态势。这一系列兼容的以安全为中心的软件可加快事件调查和响应速度。SOAR平台提高了对所有安全数据的可见性,简化了IT流程,自动执行了与安全相关的手动任务,

[EI复现】基于主从博弈的新型城镇配电系统产消者竞价策略(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。⛳️座右铭:行百里者,半于九十。📋📋📋本文目录如下:🎁🎁🎁目录💥1概述📚2运行结果🎉3参考文献🌈4Matlab代码实现💥1概述新型城镇的发展需要实现能源结构清洁化和能源利用高效

热文推荐