【深入理解Java虚拟机】垃圾收集器

本文详细介绍了Java中的垃圾收集器,包括新生代的Serial、ParNew、ParallelScavenge收集器,老年代的SerialOld、ParallelOld、CMS收集器,以及整体堆的G1收集器。解释了每种收集器的特点、适用场景及其工作原理。

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

垃圾收集器可以分为三类

  • 新生代:Serial PraNew Parallel Scavenge
  • 老年代:Serial Old Parallel Old CMS
  • 回收整个Java堆(新生代和老年代):G1

可以实现的排列组合为:

新生代垃圾收集器

1.Serial串行收集器-复制算法

Serial收集器是新生代单线程收集器,优点是简单高效,算是最基本、发展历史最悠久的收集器。它在进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集完成。

Serial收集器依然是虚拟机运行在Client模式下默认新生代收集器,对于运行在Client模式下的虚拟机来说是一个很好的选择。

2.ParNew收集器-复制算法

ParNew收集器是新生代并行收集器,其实就是Serial收集器的多线程版本。

除了使用多线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The Worl、对象分配规则、回收策略等都与Serial 收集器完全一样。

3.Parallel Scavenge(并行回收)收集器-复制算法

Parallel Scavenge收集器是新生代并行收集器,追求高吞吐量,高效利用 CPU。

该收集器的目标是达到一个可控制的吞吐量(Throughput)。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

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

老年代垃圾收集器

1.Serial Old 收集器-标记整理算法

Serial Old是Serial收集器的老年代版本,它同样是一个单线程(串行)收集器,使用标记整理算法。这个收集器的主要意义也是在于给Client模式下的虚拟机使用

如果在Server模式下,主要两大用途:

(1)在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用

(2)作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用

2.Parallel Old 收集器-标记整理算法

Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器在1.6中才开始提供。

3.CMS收集器-标记清除算法

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。

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

CMS收集器是基于“标记-清除”算法实现的,它的运作过程相对前面几种收集器来说更复杂一些,整个过程分为4个步骤:

(1)初始标记;

(2)并发标记;

(3)重新标记;

(4)并发清除。

其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”

CMS收集器主要优点

  1. 并发收集;
  2. 低停顿。

CMS三个明显的缺点:

(1)耗cpu资源

(2)CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。在JDK1.5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活。

(3)CMS是基于“标记-清除”算法实现的收集器,手机结束时会有大量空间碎片产生。空间碎片过多,可能会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前出发FullGC。

G1

G1之前的JVM内存模型

  • 新生代:伊甸园区(eden space) + 2个幸存区
  • 老年代
  • 持久代(perm space):JDK1.8之前
  • 元空间(metaspace):JDK1.8之后取代持久代

G1收集器的内存模型

G1堆内存结构

堆内存会被切分成为很多个固定大小区域(Region),每个是连续范围的虚拟内存。

堆内存中一个区域(Region)的大小可以通过-XX:G1HeapRegionSize参数指定,大小区间最小1M、最大32M,总之是2的幂次方。

默认把堆内存按照2048份均分。

G1堆内存分配

每个Region被标记了E、S、O和H,这些区域在逻辑上被映射为Eden,Survivor和老年代。

存活的对象从一个区域转移(即复制或移动)到另一个区域。区域被设计为并行收集垃圾,可能会暂停所有应用线程。

如上图所示,区域可以分配到Eden,survivor和老年代。此外,还有第四种类型,被称为巨型区域(Humongous Region)。Humongous区域是为了那些存储超过50%标准region大小的对象而设计的,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。

G1回收流程

在执行垃圾收集时,G1以类似于CMS收集器的方式运行。

G1收集器的阶段分以下几个步骤:

1)G1执行的第一阶段:初始标记(Initial Marking )

这个阶段是STW(Stop the World )的,所有应用线程会被暂停,标记出从GC Root开始直接可达的对象。

2)G1执行的第二阶段:并发标记

从GC Roots开始对堆中对象进行可达性分析,找出存活对象,耗时较长。当并发标记完成后,开始最终标记(Final Marking )阶段

3)最终标记

标记那些在并发标记阶段发生变化的对象,将被回收。

4)筛选回收

首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计划,回收一部分Region。

最后,G1中提供了两种模式垃圾回收模式,Young GC和Mixed GC,两种都是Stop The World(STW)的。

G1的GC模式

1.YoungGC年轻代收集

在分配一般对象(非巨型对象)时,当所有eden region使用达到最大阀值并且无法申请足够内存时,会触发一次YoungGC。每次younggc会回收所有Eden以及Survivor区,并且将存活对象复制到Old区以及另一部分的Survivor区。

YoungGC的回收过程如下:

  • 根扫描,跟CMS类似,Stop the world,扫描GC Roots对象。
  • 处理Dirty card,更新RSet.
  • 扫描RSet,扫描RSet中所有old区对扫描到的young区或者survivor去的引用。
  • 拷贝扫描出的存活的对象到survivor2/old区
  • 处理引用队列,软引用,弱引用,虚引用

2. mixed gc

当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。

G1没有fullGC概念,需要fullGC时,调用serialOldGC进行全堆扫描(包括eden、survivor、o、perm)。

G1的推荐用例

G1的第一个重要特点是为用户的应用程序的提供一个低GC延时和大内存GC的解决方案。这意味着堆大小6GB或更大,稳定和可预测的暂停时间将低于0.5秒。

如果应用程序使用CMS或ParallelOld垃圾回收器具有一个或多个以下特征,将有利于切换到G1:

  • Full GC持续时间太长或太频繁
  • 对象分配率或年轻代升级老年代很频繁
  • 不期望的很长的垃圾收集时间或压缩暂停(超过0.5至1秒)

注意:如果你正在使用CMS或ParallelOld收集器,并且你的应用程序没有遇到长时间的垃圾收集暂停,则保持与您的当前收集器是很好的,升级JDK并不必要更新收集器为G1。

g1更多参考:http://blog.jobbole.com/109170/

配置垃圾回收器参数

-XX:+UseSerialGC:在新生代和老年代使用串行收集器
-XX:+UseParNewGC:在新生代使用并行收集器
-XX:+UseParallelGC :新生代使用并行回收收集器,更加关注吞吐量
-XX:+UseParallelOldGC:老年代使用并行回收收集器
-XX:ParallelGCThreads:设置用于垃圾回收的线程数
-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:+UseG1GC:启用G1垃圾回收器

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值