Java常见的GC有哪些?

本文旨在为Java GC提供入门概念,后续将深入探讨调优思路。介绍了主流Oracle JDK的垃圾收集机制,如Serial GC、ParNew GC等。还阐述了垃圾收集原理,包括判断对象回收的引用计数和可达性分析算法,以及复制、标记 - 清除、标记 - 整理等GC算法和GC工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前就说,想在专栏中总结一下GC调优的相关思路和解决措施,但是准备在此篇专栏中对于GC有一个入门的概念,在明天的专栏中更进一步的去写GC调优的核心思路。

Java的垃圾收集器机制是java的招牌能力,并且目前也在不断的演进,极大地提升了开发效率,专栏尽量会将面试的重点总结起来。

那么,问题就是,java 的垃圾收集器,常见的都有哪几种?

概述

实际上,gc是与jvm紧密相关的,不同厂商IBM Oracle,不同版本的jvm,提供的选择也不一样。接下来,主要会说一下主流的oracle jdk的垃圾收集机制。

  • Serial GC。

它是最古老的的垃圾收集器,其手机工作是单线程的,并且在进行垃圾收集的过程中,会进入臭名昭著的Stop The World状态。

当然,其单线程设计也意味着最精简的GC实现,无需维护复杂的数据结构,初始化也简单,所以一直是c端的jvm默认选项。

其主要采用的算法是标记-整理(Mark-Compact)算法,区别于新生代的复制算法 。

Serial GC的对应jvm参数是:

-Xx:+UseSerialGC

  • ParNew GC

新生代GC,在Serial GC的基础上进行了多线程的扩展,其对应参数是:

-XX:+UseConcMarkSweepGC -XX:+UseParNewGC

  • CMS (Concurrent Mark Sleep) GC

基于标记清除(mark-Sleep)算法,设计目标是尽量减少停顿时间,这一点对于web等反应时间敏感的应用非常重要,一直到今天,仍然会有很多人用CMS GC。但是存在着内存碎片化的问题,所以难以避免发生full GC ,导致恶劣的停顿。另外,既然使用到了并发,CMS就会占用更多的CPU资源,和用户端线程争抢。

  • Parrallel GC

在jdk8中,它是server模式下默认的gc选择。算法与serial gc类似,特点是并行进行,效果更出色。

开启选项是:

-XX:+UseParallelGC

另外,Parrallel gc引入了设置暂停时间或者吞吐量等目标,jvm会自动进行适应性调整,例如:

-XX:MaxGCPauseMillis=value’
-XX:GCTimeRatio=N // GC时间和用户时间比例 = 1 / (N+1)

  • G1 GC

这是一款兼顾吞吐量和停顿时间的gc实现,是jdk9之后的默认gc。它可以设定停顿时间,将最差情况得到一定的改善。

G1吞吐量和停顿表现都非常不错,并且仍然在不断地完善,与此同时CMS已经在JDK 9中被标记为废弃(deprecated),所以G1 GC值得你深入掌握。

接下来会侧重介绍以下两点:、

  1. GC的算法有哪些,如何判断一个对象是否可以回收。
  2. GC工作流程

另外,java在最新的jdk实现中,混杂着多种的新gc,以下都会进行介绍。

扩展

  1. 垃圾收集的原理和基本概念

※第一,自动收集垃圾的前提是,知道什么是垃圾,然后才能释放掉。主要释放掉的为两方面,最主要的还是存储在堆上的对象实例;另外还有方法区的元数据信息,如果该类后续不再时候,就会被释放掉内存。

既然提到了对象实例的回收,那么就来说说回收的算法,主要是两种:引用计数和可达性分析

  • 引用计数

顾名思义,给对象加一个引用的计数,当计数为0就回收。这是很多语言的资源回收选择,例如py,它同时支持java没有选择的引用计数和垃圾收集机制。

  • 还有java选择的可达性分析。

java的各种引用的关系,十分混乱甚至会让可达性分析复杂化,这种类型通常称为追踪性垃圾收集。原理简单来说jvm会将java虚拟机栈,本地栈正在引用的对象或者常量称之为GC Roots,与其之间存在调用关系的,就是有用的,不存在调用关系的,就是没用的,没用的就回收

※第二、gc算法总体主要分为三类:

  • 复制(Copy)算法。

包括前面说到的新生代gc,原理就是将还存活的对象进行复制,并且顺序存储,这样还能顺便满足内存碎片化。

这样做的缺点是:浪费内存,当维护g1 gc这种算法的时候,由于不同region之间存在一定的相互调用的关系,那么就需要维护这种关系的前提进行复制,又是一笔开销。

  • 标记-清除(Mark-sleep)算法。

首先标记没用的对象,然后清除掉。

这样做的缺点是:效率低,出现内存碎片化的问题,会导致出现Full GC,造成间歇性停顿,很难受。

  • 标记-整理(Mark-Compact)

在Mark-Sleep的基础上,为了避免内存碎片化,将清除掉的garbage后的对象按照顺序移动,使他们能占用连续的内存空间。

要注意,这些都是gc的基础,实际的gc算法,多用到复合并行算法

而且,在gc的过程中,对应到Eden、Survior、Tenured等区域会发生一定的变化。
一说这个,就又不得不说一下gc的流程:

  1. java应用不断创建出对象,分配在Eden区域,当对象占用到阈值,就会触发minor GC。在满了之后,仍然被使用的对象被jvm复制到Survivor区域,不再引用的就回收。图中标记数字1的代表,被筛选过一轮的对象,生命值原本是0,现在变成1了。

在这里插入图片描述

  1. 经过了一次的复制-回收之后,Eden就会闲下来,当第二次Eden又满了的时候,继续触发Minor GC,这时候另一个Survivor区域会变成to区域,Eden又活下来的和From区域的对象会被复制到to区域,并且存活年龄+1。在这里插入图片描述

  2. 重复进行第二步,超越阈值的对象,晋升到老年代。阈值可以自定义。

-XX:MaxTenuringThreshold=<N>

在这里插入图片描述

后面就是老年代的选项了,具体取决于选择哪种gc。以下用标记-整理(Mark-Compact)举例,当老年代的无用对象被清除后,gc会对对象进行整理,以防止内存碎片化。

在这里插入图片描述

通常将老年代GC叫做Major GC,将整个堆的清理叫做Full GC,但是以上的举例是片面的,不同针对老年代的gc算法大不相同,还要继续去学习。例如cms,并行gc计算,就和以上完全不相同了。

接下来的专栏,会对gc调优进一步解析。

<think>嗯,我现在得回答Java常见的垃圾回收器。这个问题看起来基础,但可能涉及不同的类型和各自的特点。让我回忆一下学过的内容。 首先,Java的垃圾回收器有不同的种类,每种适用于不同的场景。我记得有Serial、Parallel、CMS、G1这些。不过具体细节可能记不太清了。 Serial收集器应该是最早的,单线程的,用于客户端应用,比如桌面程序。它进行垃圾回收时会暂停所有工作线程,也就是Stop-The-World。这可能就是它的缺点,但简单高效,适用于小内存的情况。 然后是Parallel,也叫吞吐量收集器。它和Serial类似,但使用多线程进行垃圾回收,所以在多核CPU上表现更好,适合后台处理任务,注重吞吐量。比如那些需要处理大量数据,对延迟不敏感的应用。 CMS,Concurrent Mark Sweep,是并发标记清除的收集器。目标是最短停顿时间,适用于需要低延迟的服务端应用。它分为多个阶段,大部分工作可以和用户线程并发执行。不过可能产生内存碎片,而且在Java 8之后被废弃了,被G1取代。 G1收集器,Garbage-First,设计用于大堆内存,将堆分成多个Region,优先回收垃圾最多的区域。它兼顾吞吐量和低延迟,适合多核大内存的服务器。JDK 9之后成为默认的收集器。 还有后来出现的ZGC和Shenandoah,它们都是低延迟的,几乎可控制的停顿时间,适用于非常大的堆内存。ZGC是JDK 11引入的,Shenandoah虽然也是JDK的一部分,但可能不在所有版本默认提供。 需要确认一下各个收集器的名称和特点是否正确。比如,Parallel Scavenge和Parallel Old是配合使用的,而CMS可能只用于老年代,配合ParNew。还有G1是否分代,虽然G1本身也是分代的,但Region的设计不同。 另外,Epsilon收集器是一个不进行垃圾回收的,用于性能测试或者已知任务不产生垃圾的情况,由JDK 11引入。 总结的话,常见的垃圾回收器包括:Serial、Parallel(包括Parallel Scavenge和Parallel Old)、CMS、G1、ZGC、Shenandoah,以及Epsilon。每种都有适用的场景和特点,比如吞吐量、延迟、内存大小等。</think><< Java常见的垃圾回收器主要有以下类型: 1. **Serial收集器** - **特点**:单线程工作,回收时会触发STW(Stop-The-World),适用于客户端或小内存场景。 - **使用方式**:通过`-XX:+UseSerialGC`启用。 2. **Parallel/吞吐量收集器(Parallel Scavenge + Parallel Old)** - **特点**:多线程并行回收,关注吞吐量(应用程序运行时间占比),适合后台计算任务。 - **使用方式**:通过`-XX:+UseParallelGC`和`-XX:+UseParallelOldGC`启用。 3. **CMS(Concurrent Mark Sweep)收集器** - **特点**:以最短停顿时间为目标,采用标记-清除算法,但会产生内存碎片。 - **使用方式**:通过`-XX:+UseConcMarkSweepGC`启用(JDK 8及之前)。 4. **G1(Garbage-First)收集器** - **特点**:将堆划分为多个Region,通过预测停顿时间实现高吞吐和低延迟,适用于大内存场景。 - **使用方式**:通过`-XX:+UseG1GC`启用(JDK 9+默认)。 5. **ZGC(Z Garbage Collector)** - **特点**:支持超大堆(TB级),停顿时间不超过10ms,通过染色指针和读屏障实现并发。 - **使用方式**:通过`-XX:+UseZGC`启用(JDK 15+正式支持)。 6. **Shenandoah收集器** - **特点**:与ZGC类似,但通过Brooks指针实现并发压缩,适用于低延迟场景。 - **使用方式**:通过`-XX:+UseShenandoahGC`启用(需特定JDK版本支持)。 7. **Epsilon收集器** - **特点**:无实际垃圾回收,仅分配内存,用于性能测试或极短生命周期任务。 - **使用方式**:通过`-XX:+UseEpsilonGC`启用。 **代码示例**(如何指定垃圾回收器): ```java // 运行Java程序时添加JVM参数指定垃圾回收器 // 例如使用G1收集器: // java -XX:+UseG1GC MyApplication public class MyApplication { public static void main(String[] args) { System.out.println("Hello, GC!"); } } ``` **解释**: 垃圾回收器的选择需根据应用场景权衡: - **低延迟**:优先选G1、ZGC或Shenandoah。 - **高吞吐**:使用Parallel收集器。 - **极小内存或测试**:Serial或Epsilon。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值