【006】【JVM——垃圾收集器总结】



JVM——垃圾收集器总结

垃圾收集器概览

收集算法是内存回收的方法论,垃圾收集据是内存回收的具体实现。Java虚拟机规范中对垃圾收集器应该如何实现没有规定,不同的厂商、不同版本的虚拟机所提供的垃圾收集器可能会有很大差别,一般都会提供参数供用户根据自己的所用特点和要求组合出各个年代所使用的收集器。下面是基于JDK
1.7 Update 14 之后的HotSpot 虚拟机垃圾收集器。如果两个收集器之间有连线就说明它们可以搭配使用。直到现在还没有最好的收集器,更加设有万能的收集器,只是对具体应用选择最合适的收集器。

垃圾收集器概览图如下:

Serial 收集器

Serial 收集器是最基本、历史最悠久的收集器,它是一个单线程的收集器,即它只会使用一个CPU 或一条收集线程去完成垃圾收集工作,而且在进行垃圾收集时, 必须暂停其他所有的工作钱程,直到它收集结束,虽然它有很大缺点,但依然是虚拟机运行在Client 模式下的默认新生代收集器。它也有着优于其他收集器的地方: 简单而高效。Serial 收集器没有线程交互的开销, 专心做垃圾收集,可以获得很高的单线程收集效率。

运行示意图如下:

ParNew 收集器

ParNew 收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为包括Serial 收集器可用的所有控制参数、、收集算法、应用停机(Stop
The World)、对象分配规则、回收策略等都与Serial 收集器完全一样。ParNew是许多运行在Server 模式下的虚拟机中首选的新生代收集器。目前只有它能与CMS 收集器配合工作。ParNew 收集器在单CPU 的环境中不会有比Serial 收集器效果好。随着使用的CPU 的数量的增加,它对于GC 时系统资源的利用提高。

垃圾收集的上下文语境中:

  • 并行( Parallel ):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
  • 并发( Concurrent ):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序继续运行,垃圾收集程序运行在另一个CPU 上。

Parallel Scavenge 收集器

Parallel Scavenge 收集器是一个新生代收集器,使用复制算法,是并行的多线程收集器。Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。吞吐量就是CPU 用于运行用户代码的时间与CPU 总消耗时间的比值,即 吞吐量=运行用户代码时间/( 运行用户代码时间+垃圾收集时间)。

高吞吐量可以最高效率地利用CPU 时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。Parallel Scavenge 收集器也经常称为“吞吐量优先”收集器。

Serial Old 收集器

Serial Old 是Serial 收集器的老年代版本, 也是一个单线程收集器,使用“标记一整理”算法。主要被Client 模式下的虚拟机使用。如果在Server 模式下,有两大用途: 一个是在JDK
5 以及之前的版本中与Parallel Scavenge 收集器搭配使用。另一个就是作为CMS 收集器的后备预案,在并发收集发生Concurrent
Mode Failure 的时候使用。

运行示意图如下:

Parallel Old 收集器

Parallel Old 是Parallel Scavenge 收集器的老年代版本,使用多线程和“标记一整理”算法。

运行示意图如下:

CMS 收集器

CMS( Concurrent Mark Sweep ) 收集器是一种以获取最短回收停顿时间为目标的收集器。停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。目前很大一部分的Java 应用都集中在互联网站或B/S 系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS 收集器就非常符合这类应用的需求。

CMS 收集器是基于“标记一清除”算法实现的,整个过程分为4 个步骤:

    1. 初始标记( CMS initial mark): 需要“Stop
      The World ”。初始标记仅仅只是标记一下GC Roots 能直接关联到的对象,速度很快。
    2. 并发标记( CMS concurrent mark):并发标记阶段就是进行GCRoots
      Tracing 的过程
    3. 重新标记( CMS remark) : 需要“Stop
      The World ”。为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短
    4. 并发清除( CMS concurrent sweep):进行垃圾清理工作。

运行示意图如下:

优点:并发收集、低停顿。

缺点:

CMS 收集器对CPU 资源非常敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程(或者说CPU 资源)而导致应用程序变慢,总吞吐量会降低。CMS 默认启动的回收线程数是(CPU 数量+3)/
4 。

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

收集结束时会产生大量空间碎片。CMS 基于“标记一清除”算法实现。多次垃圾收集后,空间碎片过多,给大对象分配带来很大的麻烦,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full
GC 。为了解决这个问题, CMS 收集器提供了-XX:+UseCMSCompactAtFullCollection 这个参数,用于在CMS收集器要进行FullGC时开启内存碎片整理。默认值为0,表示每次进入FullGC 时都进行碎片整理

G1 收集器

收集器技术发展的最新成果,是面向服务端应用的垃圾回收器。它有下面的特点:

  • 并发与并行:能利用多CPU、多核环境下优势,使用多个CPU
    (CPU或者CPU 核心)来缩短Stop The World 的停顿时间。部分其他收集器原本需要停顿Java 线程执行的GC动作, G1 收集器仍然可以通过并友的方式让Java 程序继续执行
  • 分代收集:G1中依然使用分代概念。G1可以不需要其他收集器配合就能独立管理整个GC 堆,还能够用不同的方式去处理新创建的对象和已经存在一段时间、经过多次GC 依旧存在的对象,进而获得更好的收集效果.
  • 空间整合:GI从整体来看是基于“标记一整理”算法, 从局部(两个Region 之间)后是基于“复制” 算法实现的,这意味着GI1运行期间不会产生内存空间碎片,收集后能提供规整的可用内存. 这种特性有利于程序长时间运行,分配大的对象不会因为无法找到连续内存空间而提前触发下一次GC。
  • 可预测的停顿:GI 除了低停顿外,还能建立预测的停顿时间的模型,能让使用者明确指定在一个长度为M 毫秒的时间片段内,垃圾收的时间不得超过N 毫秒。

使用GI 收集器时,Java 堆的内存布局就与其他收集器有很大差别,它将整个Java 堆划分为多个大小相等的独立区域(Region),虽然保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离,它们都是一部分Region(不需要连续)的集合。

G1收集器能建立预测的停顿时间模型,是因为它可以有计划地避免在整个Java 堆中进行全区域的垃圾收集。G1跟踪各个Region 里每个垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先队列,根据允许的收集时间,优先回收价值最大的Region (这也就是Garbage-First 名称的来由)。这种使用Region 划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。

在GI 收集器中, Region 之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用, 虚拟机都是使用Remembered
Set 来避免全堆扫描。

不计算维护Remembered Set 的操作, GI收集器的运作可划分为以下四个步骤:

    1. 初始标记(Initial Marking):仅标记GC
      Roots能直接关联到的对象并且修改TAMS(Next to Top at Mark Start)的值。让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这个阶段要停顿线程,但耗时短。
    2. 并发标记(Concurrent Marking):从GC
      Roots开始对堆中对象进行可达性分析,找出存活对象,这个阶段耗时少,可以与用户程序并发执行。
    3. 最终标记(Final Marking):为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,虚拟机将这段时间变化记录在线程Remembered
      Set中,这个阶段可以并行执行。
    4. 筛选回收(Live Data Counting and Evacuation):对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,可以与用户程序并发执行。

运行示意图如下:

【参见】【深入理解Java虚拟机(第二版)】【周志明】

时间: 2024-10-05 12:43:13

【006】【JVM——垃圾收集器总结】的相关文章

第六章 JVM垃圾收集器(2)

上一章记录了几种常见的垃圾收集器,见<第五章 JVM垃圾收集器(1)> 1.G1 说明: 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除),实际上G1回收器的整个堆内存的划分都与其他收集器不同. CMS需要配合ParNew,G1可单独回收整个空间 原理: G1收集器将整个堆划分为多个大小相等的Region G1跟踪各个region里面的垃圾堆积的价值(回收后所获得的空间大小以及回收所需时间长短的经验值),在后台维护一张优先列表,每次根据允许的

JVM垃圾收集器

1.垃圾回收器类型 1.串行垃圾回收器(Serial Garbage Collector) 2. 并行垃圾回收器(Parallel Garbage Collector) 3. 并发标记扫描垃圾回收器(CMS Garbage Collector) 4. G1垃圾回收器(G1 Garbage Collector) 1.串行垃圾回收器(Serial Garbage Collector) 串行垃圾回收器通过持有应用程序所有的线程进行工作.它为单线程环境设计,只使用一个单独的线程进行垃圾的回收,通过冻结所

JVM垃圾收集器(1)

此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见<第四章 JVM垃圾回收算法> 1.七种垃圾收集器 Serial(串行GC)-- 复制 ParNew(并行GC)-- 复制 Parallel Scavenge(并行回收GC)-- 复制 Serial Old(MSC)(串行GC)-- 标记-整理 CMS(并发GC)-- 标记-清除 Parallel Old(并行GC)--标记-整理

JVM垃圾收集器-Parallel Scavenge收集器

今天我给大家讲讲JVM垃圾收集器-Parallel Scavenge收集器 Parallel Scavenge收集器 ? ? ? ?Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的收集器,又是并行的多线程收集器,看上去和ParNew都一样,那它有什么特别之处呢? ? ? ??Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标是

5种JVM垃圾收集器特点和8种JVM内存溢出原因

先来看看5种JVM垃圾收集器特点 一.常见垃圾收集器 现在常见的垃圾收集器有如下几种: 新生代收集器: Serial ParNew Parallel Scavenge 老年代收集器: Serial Old CMS Parallel Old 堆内存垃圾收集器:G1 每种垃圾收集器之间有连线,表示他们可以搭配使用. 二.新生代垃圾收集器 (1)Serial 收集器 Serial 是一款用于新生代的单线程收集器,采用复制算法进行垃圾收集.Serial 进行垃圾收集时,不仅只用一条线程执行垃圾收集工作,

记一次有关于Jvm垃圾收集器的整理

记一次有关于Jvm垃圾收集器的整理 垃圾回收器 算法: 引用计数法 复制算法 标记清楚 标记整理 垃圾回收的方式 1.Serial:串行回收 2.Parallel:并行回收 3.CMS:并发标记清除 4.G1:G1 截止到java10               之后有ZGC Seial:串行垃圾回收,单线程垃圾回收的时候会停掉用户的线程进行垃圾回收不适合服务器的环境 Parallel:并行垃圾回收多个垃圾收集线程并行工作也会停掉垃圾回收的时候用户的线程 CMS:用户线程和垃圾回收线程同时执行(

jvm 垃圾收集器分析

jvm 垃圾收集器分析 jvm 垃圾收集器分析   新生代收集器 老年代收集器 优点 缺点 serial收集器 V   1.jdk1.3开始的单线程收集器 2.client模式下很好的选择. 3.复制算法 1.单线程,收集时需要暂停所有线程(stop the world) parNew收集器 V   1.serial的多线程版 2.server模式下 3.可与CMS收集器工作 4.线程数与cpu数相同 1.单CPU下不会比serial收集器性能好   Parallel Scavenge 收集器

深入了解JVM垃圾收集器

程序计数器.JVM栈.本地方法栈这三个内存区域和线程是一一对应的,并且每一个线程的这三个区域相互独立互不干扰.他们都随着线程的产生而产生,线程的灭亡而灭亡.JVM栈和本地方法栈中的栈帧都随着方法的加载而入栈,随着方法的结束而出栈. 栈帧的大小是在程序员写类的时候就确定下来的.因此这三种区域的内存大小都具备确定性,当方法结束或线程结束后,这些内存空间就会自动被回收掉,所以JVM无需考虑这些区域的内存回收问题. 堆内存和方法区的内存分配和回收就不一样了,因为一个接口中的多个实现类所需要的内存可能不一

【JVM】JVM垃圾收集器、垃圾收集算法、无用对象

Java 常见的垃圾收集器有哪些 实际上,垃圾收集器(GC,Garbage Collector)是和具体 JVM 实现紧密相关的,不同厂商(IBM.Oracle),不同版本的JVM,提供的选择也不同.接下来,我来谈谈最主流的 Oracle JDK. Serial GC 它是最古老的垃圾收集器,"Serial"体现在其收集工作是单线程的,并且在进 行垃圾收集过程中,会进入臭名昭著的"Stop-The-World"状态.当然,其单线程设计也意味着精简的 GC 实现,无需