GC 垃圾收集器

article/2025/11/5 4:03:37

GC 垃圾回收算法 和 垃圾收集器之间的关系是什么呢 ?

  1. GC算法 (复制 / 标清 / 标整 ) 是内存回收的一种思想 , 垃圾收集器就是 GC算法 的落地实现
  2. 我们知道没有最完美的 GC算法 , 因此目前为止也没有完美的垃圾收集器 , 只是针对不同的情况选择最适合的收集器来进行分代收集

主要垃圾收集器概述

1. 串行垃圾回收器 ( Serial )

它为单线程环境设计 , 且只使用一个线程进行垃圾回收 , 会暂停所有的用户线程 ( STW ) , 所以不适合服务器环境

2. 并行垃圾回收器 ( Parallel )

多个垃圾收集线程并行工作,此时用户线程是暂停的 ( STW ) , 适用于科学计算/大数据后台处理等弱交互场景 (弱交互指的是 : 非立刻响应的场景 )

3. 并发垃圾回收器 ( CMS )

用户线程和垃圾收集线程同时执行 (不一定是并行,可能交替执行),不需要停顿用户线程 , 互联网公司多用它,适用对响应时间有要求的场景

查看默认的垃圾收集器

JVM 参数:

java -XX:+PrintCommandLineFlags -version

默认的使用的并行垃圾收集器

默认的垃圾收集器有哪些 ?

java 的 gc 回收的类型主要有几种 :

UseSerialGC,UseParallelGC,UseConcMarkSweepGC,

UseParNewGC,UseParallelOldGC,UseG1GC

垃圾收集器


垃圾收集器 : 具体实现这些GC算法并实现内存回收。

 

新生区中使用的GC有 :  Serial (串行)    ParNew ( 并行)     Parallel Scavenge ( 吞吐量优先收集器 )

老年代中使用的GC有 :  Serial Old             CMS                        Parallel Old Serial Old

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

G1 横跨新生区以及老年代

他们之间的联系就是 : 比如 :你在新生区使用了串行 ( Serial ) 那么在老年代中你只能使用 Serial Old 

串行 (Serial ) / ( Serial Copying )

一个单线程的收集器 , 在进行垃圾收集时候 , 必须暂停其他所有的工作线程 ( STW ) , 直到它收集结束

 串行收集器组合 Serial + Serial Old

串行收集器是最古老,最稳定以及效率高的收集器 , 只使用一个线程去回收 , 但是在进行垃圾收集过程中可能会产生较长的停顿(Stop - The - World 状态)。虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于单个CPU 环境来说,没有线程交互的情况下 , 它的单线程垃圾收集效率是最高的 , 因此 Serial 垃圾收集器依然是 java 虚拟机运行在 Client 模式下默认的新生代垃圾收集器。

串行收集器使用在客户端模式下的 , 而我们使用的 Java 都是作为 Server 端的 , 如果强行使用串行收集 直接会把程序拖死

JVM 参数是:-XX:+UseSerialGC

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseSerialGC

并行 ( Parallel ) / ( Parallel Scavenge ) / ParNew

Parallel Scavenge 收集器类似 ParNew 也是一个新生代垃圾收集器,使用复制算法,也是一个并行的多线程的垃圾收集器,俗称吞吐量优先收集器

就是说 : 串行收集器在新生代和老年代的并行化,Parallel 就是 Serial 收集器的升级并行版多个收集线程

JVM 参数: -XX:+UseParallelGC 或 -XX:+UseParallelOldGC ( 可互相激活 ) 

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelGC

-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseParallelOldGC

CMS 并发标记清除

1. 初始标记 ( CMS initial mark ) 会发生 STW

只是标记一下 GC Roots 能直接关联的对象 ( 可以认为此阶段仅仅遍历了一层 , 而在并发标记阶段才进行整个对象的遍历 ) , 因为直接关联对象比较小 , 所以此阶段的速度很快 , 但是仍然需要暂停所有的工作线程

2. 并发标记 ( CMS concurrent mark ) GC 线程和用户线程一起

从 GC Roots 的直接关联对象开始遍历整个对象的过程 , 此阶段耗时较长 , 但是不需要暂停用户线程 , 可以和垃圾线程一起并发运行

3. 重新标记 ( CMS remark ) 会发生 STW

为了修正在并发标记期间 , 因为用户程序继续运行导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。修正后再做清除 , 此阶段比初始标记阶段耗时要长 , 但是比并发标记阶段耗时要短

4. 并发清除 ( CMS concurrent sweep ) GC 线程和用户线程一起

清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。基于标记结果,直接清理对象由于耗时最长的并发标记和并发清除过程中,垃圾收集线程可以和用户线程一起并发工作,所以总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行。

无法避免 STW 但是可以减少 STW 的时间 ( 并发收集低停顿 )

总结

  1. CMS 收集器 (Concurrent Mark Sweep:并发标记清除)是一种以获取最短回收停顿时间为目标的收集器。
  2. 适合应用在互联网站或者 B / S 系统的服务器上,这类应用尤其重视服务器的响应速度 ,希望系统停顿时间最短。( 打个比方 : 当你使用程序的时候 , 经常会出现长时间的程序停顿 , 心态肯定是崩的 )
  3. CMS非常适合堆内存大、CPU核数多的服务器端应用 ,也是G1出现之前大型应用的首选收集器。
  4. Concurrent Mark Sweep 并发标记清除,并发收集低停顿,并发指的是与用户线程一起执行

JVM参数  : -XX:+UseConcMarkSweepGC 

-Xms10m -Xmx10m -XX:+PrintGCDetails  -XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC

CMS 回收器的优缺点

优点 : 

并发收集的低停顿

缺点 :

1. 因为使用了标记清除 , 所以会产生内存碎片 , 在并发清除后 , 用户线程的可用空间不足 , 又无法分配大对象的情况时 , 触发 Full GC , 拉低程序性能

2. CMS 的并发执行对CPU资源压力大 , 虽然不会导致太长的用户停顿 , 但是会因为占用了一部分的线程导致应用程序变慢 ( 上面的图我们可以看出它占用了用户的线程 ) 总吞吐量降低

问题来了 ? ? ?

并发标记清除 Mark  Sweep 会造成内存碎片 , 那么为什么不把算法换成Mark Compact 呢 ?

因为并发清除的时候 , 用Compact 整理内存的话 , 会将对象重新做了一个调整 , 其中的对象的地址全部在内存中发生了改变 , 我们不要忘了 并发标记清除阶段的用户线程是一直在执行的 , 对象的地址都发生了改变 , 就会导致原本正常运行的用户线程出错

Mark Compact 更适合 " STW " 这种静态的场景 

G1 

Java9 以后默认的垃圾收集器 , G1(Garbage-First)收集器,是一款面向服务端应用的收集器

为什么要出现 G1? CMS 不好吗 ?

  1. CMS 垃圾收集器虽然减少了暂停应用程序的运行时间 , 但是它还是存在着内存碎片问题。于是,为了解决内存碎片问题,同时又保留 CMS 垃圾收集器暂停时间短的优点,JAVA7 预发布了一个新的垃圾收集器 G1 垃圾收集器。
  2. 在 jdk9 中将 G1 变成默认的垃圾收集器以替代 CMS。它是一款面向服务端应用的收集器,主要应用在多CPU和大内存服务器环境下,极大的减少垃圾收集的停顿时间,全面提升服务器的性能,逐步替换 java8 以前的 CMS 收集器。

G1 收集器的设计目标是取代 CMS 收集器,它同 CMS 相比,在以下方面表现的更出色:

  1. G1 是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
  2. G1 的 Stop The World ( STW ) 更加可控,G1收集器是把整个堆(新生代、老生代)划分成多个固定大小的区域 , G1 在停顿时间上添加了预测机制,用户可以精确控制停顿时间 , 每次根据允许停顿的时间去收集垃圾最多的区域 。

主要改变是 Eden,Survivor 和 Tenured 等内存区域不再是连续的了,而是变成了一个个大小一样的 region ,每个 region 从1M 到 32M 不等。一个 region 有可能属于 Eden,Survivor 或者 Tenured内存区域。

 

可以发现:  G1 类似于 CMS 

G1 的四个阶段

初始标记 : 仅仅只是标记一下GC Roots能直接关联到的对象 , 这个阶段需要停顿线程,但耗时很短

并发标记 : 进行 GC Roots Tracing 的过程 , 对堆中对象进行可达性分析,扫描整个堆中的对象 , 找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。

最终标记 : 修正并发标记期间 , 因程序运行导致标记发生变化的那一部分对象 , 用户线程有一个短暂的暂停

筛选回收 : 根据时间来进行价值最大化的回收 , 必须暂停用户线程,

G1 的优势

  1. G1 充分利用多 CPU , 多核环境硬件优势 , 尽量缩短 STW
  2. G1整体上采用标记 / 整理算法 , 布局是通过复制算法 , 因此不会产生内存碎片
  3. 宏观上看G1之中不再区分年轻代和老年代 , 把内存划分为多个独立的子区域 ( Region ) , 像一个棋盘一样
  4. G1 收集器里面将整个的内存区都混合在一起了,但其本身依然在小范围内要进行年轻代和老年代的区分,保留了新生代和老年代,但它们不再是物理隔离的,而是一部分 Region 的集合且不需要 Region 是连续的,也就是说依然会采用不同的 GC 方式来处理不同的区域
  5. G1 虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的 survivor 做复制准备。
  6. G1 只有逻辑上的分代概念,或者说每个分区都可能随 G1 的运行在不同代之间前后切换;


http://chatgpt.dhexx.cn/article/3Rvte6t6.shtml

相关文章

7种垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根据…

垃圾收集器简介

HotSpot JVM收集器 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。 Serial(串行GC)收集器 Serial收集器是一个新生代收集器,单线程执行&…

【JVM】7种经典的垃圾收集器

文章目录 1. 垃圾收集器概述2. Serial 收集器3. ParNew 收集器4. Paraller Scavenge 收集器5. Serial Old收集器6. Parller Old收集器7. CMS 收集器8. Garbage First 收集器 本文参考:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版&#x…

JVM垃圾收集器

一.概述 GC需要完成的三件事:1.哪些内存需要回收? 2.什么时候回收? 3.如何回收 Java内存运行时区域的各个部分: a. 其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行…

垃圾收集算法与垃圾收集器

典型的垃圾收集算法 1.Mark-Sweep(标记-清除)算法 这是最基础的垃圾回收算法,之所以说它是最基础的是因为它最容易实现,思想也是最简单的。标记-清除算法分为两个阶段:标记阶段和清除阶段。标记阶段的任务是标记出所有…

Java 的七种垃圾收集器

用 C 或 C 这样的编程语言写一个应用时,需要编写代码来销毁内存中不再需要的对象。当应用程序扩展得越来越复杂时,未使用对象被忽略释放的可能性就越大。这会导致内存泄露,最终内存耗尽,在某个时刻将没有更多的内存可以分配。结果…

Java 垃圾收集器

堆内存示意图 垃圾收集算法 1.标记-清除算法 算法分为标记和清除两个阶段。标记出所有需要回收的对象,在标记完成后,统一回收。 缺点: 执行效率不稳定,若堆中有大量对象要被回收,这是必须进行大量标记和清除动作&a…

JVM 垃圾收集器

title: “JVM 垃圾收集器” date: 2022-03-11T16:45:2108:00 draft: false 文章目录 引言术语垃圾收集器介绍Serial 收集器(新生代)ParNew收集器(新生代)Parallel Scavenge收集器(新生代)Serial Old 收集器…

详解ZGC垃圾收集器

从G1垃圾收集器开始,后面的垃圾收集器都不再将堆按照新生代和老年代作为整体进行回收,都采用了局部收集的设计思想。 可能是由于G1作为第一代局部收集的垃圾收集器,所以它继续保留了新生代和老年代的概念,笔者认为从局部收集和分…

JVM——垃圾收集器

目录 引言 垃圾收集器 如何判断对象已死? 引用计数算法: 可达性分析算法: 垃圾收集算法 标记-清除算法 标记-复制算法 标记-整理算法 并发的可达性分析 经典垃圾收集器 内存分配与回收策略 1.对象优先在Eden分配 …

jvm垃圾收集器有哪些

Serial收集器 Serial收集器是最基本,发展最悠久的收集器,在JDK1.3.1之前是虚拟机新生代垃圾回收的唯一选择。这个收集器是一个单线程的。它的单线程的意义并不仅仅说明它只会使用一个CPU或者一条收集线程去完成收集工作,最重要的是&#xff…

经典垃圾收集器(三)

低延迟垃圾收集器 衡量垃圾收集器的三项重要指标:内存占用(Footprint)、吞吐量(Throughput)和延迟(Latency)。三者构成了一个“不可能三角” Shenandoah收集器 Shenandoah相比于G1有什么改进&…

垃圾收集器

如果说垃圾回收算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现,java虚拟机实现规范中对垃圾收集器应该如何实现并没有任何规定,因此不同厂商、不同版本的虚拟机提供的垃圾收集器存在很大的差异,接下来我们主要介绍…

深入理解7种垃圾收集器

**如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。**Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、版本的虚拟机所提供的垃圾收集器都可能会有很大差别,并且一般都会提供参数供用户根…

Java中的垃圾收集器

目录 1、Java的垃圾收集器的分类 2、收集器的特点 3、评估GC的性能指标 4、Serial收集器 5、ParNew收集器 6、Parallel Scavenge 吞吐量优先 (与Parallel Old搭配) 7、CMS收集器 8、G1收集器 9、各种收集器的应用场景 垃圾收集器:垃…

java垃圾收集器

目录 简介 Serial 收集器 ParNew 收集器 并行(Parallel) 并发(Concurrent) Parallel Scavenge 收集器 Serial Old 收集器 Parallel Old 收集器 CMS收集器 G1收集器 G1简介 G1细节 G1 Minor GC流程 G1 Mixed GC流程 …

常用垃圾收集器介绍

本节将会介绍一下HotSpot虚拟机中的常用垃圾收集器:Serial,ParNew,Parallel Scavenge,Serial Old,Parallel Old,CMS,G1,会对每个垃圾收集器的概念和常用参数做下介绍。 目录 概述 …

JVM-垃圾收集器

一、常见的垃圾收集器有串行垃圾回收器(Serial)、并行垃圾回收器(Parallel)、并发清除回收器(CMS)、G1回收器。 1、串行垃圾回收器。 为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所…

JVM:7种垃圾收集器

一、Serial收集器(单线程收集器) 这个收集器是一个单线程的收集器,但它的“单线程”的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程…

JVM学习----七种垃圾收集器(GC)

文章目录 GC垃圾收集器七种经典的垃圾回收器查看默认垃圾收集器新生代Serial垃圾收集器(单线程、 复制算法)ParNew 垃圾收集器 (Serial的多线程版本、 复制算法)Parallel Scavenge 收集器(多线程复制算法、高效&#x…