JVM垃圾回收器

Posted october-sy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM垃圾回收器相关的知识,希望对你有一定的参考价值。

一、串行垃圾回收器

在JDK1.3之前,单线程回收器是唯一的选择。它的单线程意义不仅仅是说它只会使用一个CPU或一个手机线程去完成垃圾收集工作。而且它进行垃圾回收的时候,必须暂停其它所有的工作线程(Stop The World,STW),直到它收集完成。在单CPU环境下,它效率高效,由于没有线程交互的开销,专心垃圾收集自然可以获得最高的单线程效率。

串行的垃圾收集器有两种,Serial和Serial Old,一般两者搭配使用。

新生代采用Serial,是利用复制算法;老年代使用Serial Old采用标记-整理算法。

二、并行垃圾回收器

并行垃圾回收器是通过多线程进行垃圾收集的。也会暂停其它所有的工作线程(Stop The World,STW)。适合Server模式以及多CPU环境。并行的垃圾回收器有以下几种:

ParNew:Serial收集器的多线程版本,默认开启的收集线程数和CPU数量一样,用于新生代收集,复制算法。和Serial Old收集器组合进行内存回收。

 Parallel Scavenge: 关注吞吐量,吞吐量优先,吞吐量=代码运行时间/(代码运行时间+垃圾收集时间),也就是高效率利用CPU时间,尽快完成程序的运算任务可以升值最大停顿时间MaxGCPauseMillis以及,吞吐量大小GCTimeRatio。用于新生代收集,复制算法。

Parllel Old:Parallel Scavenge的老年代版本。

三、CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器。从名字就能知道它是标记-清除算法的。但是它比一般的标记-清除算法要复杂一些,分为以下4个阶段:

  1. 初始标记:标记一下GC Roots能直接关联到的对象,会"Stop The World"。
  2. 并发标记:GC Roots Tracing,可以和用户线程并发执行。
  3. 重新标记:标记期间产生的对象存活的再次判断,修正对这些对象的标记,执行时间相对并发标记短,会“Stop The World”。
  4. 并发清除:清除对象,可以和用户线程并发执行。

由于它是基于标记-清除算法的,那么就无法避免空间碎片的产生。CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。

所谓浮动垃圾,在CMS并发清理阶段用户线程还在运行着,伴随程序运行自然还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只能留待下一次GC时再清理掉。

四、G1垃圾收集器

G1从整体看还是基于标记-清除算法的,但是局部上是基于复制算法的。这样就意味者它空间整合做的比较好,因为不会产生空间碎片。G1还是并发与并行的,它能够充分利用多CPU、多核的硬件环境来缩短“stop the world”的时间。G1收集器的运作大致可以分为以下步骤:初始标记、并发标记、最终标记、筛选回收。其中初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这个阶段需要STW,但耗时很短。并发标记阶段是从GC Roots开始对堆中对象进行可达性分析,找到存活的对象,这阶段耗时较长,但是可以和用户线程并发运行。最终标记阶段则是为了修正在并发标记期间因用户程序继续运行而导致标记产生变化的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记需要把Remembered Set Logs的数据合并到Remembered Sets中,这阶段需要暂停线程,但是可并行执行。最后的筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来确定回收计划。

分代收集器

分为新生代和老年代,新生代大概占1/3,老年代大概占2/3;

新生代包括Eden、From Survivor、To Survivor;

Eden区和两个survivor区的 的空间比例 为8:1:1 ;

垃圾回收器的执行流程:

把 Eden + From Survivor 存活的对象放入 To Survivor 区;
清空 Eden + From Survivor 分区,From Survivor 和 To Survivor 分区交换;
每次交换后存活的对象年龄+1,到达15,升级为老年代,大对象会直接进入老年代;
老年代中当空间到达一定占比,会触发全局回收,老年代一般采取标记-清除算法;

Full GC

G1在对象复制/转移失败或者没法分配足够内存(比如巨型对象没有足够的连续分区分配)时,会触发Full GC。Full GC使用的是stop the world的单线程的Serial Old模式,所以一旦触发Full GC则会STW应用线程,并且执行效率很慢。JDK 8版本的G1是不提供Full GC的处理的。对于G1 GC的优化,很大的目标就是没有Full GC。

JVM垃圾收集器

1.垃圾回收器类型

1.串行垃圾回收器(Serial Garbage Collector)
2.
  1. 并行垃圾回收器(Parallel Garbage Collector)
3.
        1. 并发标记扫描垃圾回收器(CMS Garbage Collector)
                1. 4.
                                  1. G1垃圾回收器(G1 Garbage Collector)


1.串行垃圾回收器(Serial Garbage Collector)
串行垃圾回收器通过持有应用程序所有的线程进行工作。它为单线程环境设计,只使用一个单独的线程进行垃圾的回收,通过冻结所有应用程序线程进行工作,不适合服务器环境。

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

并行垃圾回收器也叫做 throughput collector 。它是JVM的默认垃圾回收器。与串行垃圾回收器不同,它使用多线程进行垃圾回收。相似的是,当执行垃圾回收的时候它也会冻结所有的应用程序线程

3.
        1. 并发标记扫描垃圾回收器(CMS Garbage Collector)

并发标记垃圾回收使用多线程扫描堆内存,标记需要清理的实例并且清理被标记过的实例。

        1. 4.
                          1. G1垃圾回收器(G1 Garbage Collector)

G1垃圾回收器适用于堆内存很大的情况,他将堆内存分割成不同的区域,并且并发的对其进行垃圾回收。G1也可以在回收内存之后对剩余的堆内存空间进行压缩。

2.JVM垃圾收集器

 有连线的2个垃圾收集器可以搭配使用
1.Serial垃圾收集器
Serial是一个单线程的收集器,使用复制算法,在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束,所以垃圾收集的过程中会Stop The World(服务暂停)
Serial是最基本、历史最悠久的垃圾收集器,曾经是JDK1.3.1之前新生代唯一的垃圾收集器。
Serial是一个单线程的收集器,它不仅仅只会使用一个CPU或一条线程去完成垃圾收集工作,并且在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。
Serial垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限定单个CPU环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器依然是java虚拟机运行在Client模式下默认的新生代垃圾收集器

2.ParNew垃圾收集器
Serial收集器的多线程版本

ParNew垃圾收集器其实是Serial收集器的多线程版本,也使用复制算法,除了使用多线程进行垃圾收集之外,其余的行为和Serial收集器完全一样,ParNew垃圾收集器在垃圾收集过程中同样也要暂停所有其他的工作线程。

ParNew收集器默认开启和CPU数目相同的线程数,可以通过-XX:ParallelGCThreads参数来限制垃圾收集器的线程数。

ParNew虽然是除了多线程外和Serial收集器几乎完全一样,但是ParNew垃圾收集器是很多java虚拟机运行在Server模式下新生代的默认垃圾收集器


3.Parallel Scavenge收集器
Parallel Scavenge收集器也是一个新生代垃圾收集器,同样使用复制算法,也是一个多线程的垃圾收集器,它重点关注的是程序达到一个可控制的吞吐量(Throughput,CPU用于运行用户代码的时间/CPU总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)),高吞吐量可以最高效率地利用CPU时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。

Parallel Scavenge收集器提供了两个参数用于精准控制吞吐量:
a.-XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间,是一个大于0的毫秒数。
b.-XX:GCTimeRation:直接设置吞吐量大小,是一个大于0小于100的整数,也就是程序运行时间占总时间的比率,默认值是99,即垃圾收集运行最大1%(1/(1+99))的垃圾收集时间。
Parallel Scavenge是吞吐量优先的垃圾收集器,它还提供一个参数:-XX:+UseAdaptiveSizePolicy,这是个开关参数,打开之后就不需要手动指定新生代大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRation)、新生代晋升年老代对象年龄(-XX:PretenureSizeThreshold)等细节参数,虚拟机会根据当前系统运行情况收集性能监控信息,动态调整这些参数以达到最大吞吐量,这种方式称为GC自适应调节策略,自适应调节策略也是ParallelScavenge收集器与ParNew收集器的一个重要区别

4.Serial Old收集器
Serial Old是Serial垃圾收集器年老代版本,它同样是个单线程的收集器,使用标记-整理算法,这个收集器也主要是运行在Client默认的java虚拟机默认的年老代垃圾收集器。

5.Parallel Old收集器
Parallel Old收集器是Parallel Scavenge的年老代版本,使用多线程标记-整理算法,在JDK1.6才开始提供。
在JDK1.6之前,新生代使用Parallel Scavenge收集器只能搭配年老代的Serial Old收集器,只能保证新生代的吞吐量优先,无法保证整体的吞吐量,Parallel Old正是为了在年老代同样提供吞吐量优先的垃圾收集器,如果系统对吞吐量要求比较高,可以优先考虑新生代Parallel Scavenge和年老代Parallel Old收集器的搭配策略。

6.CMS收集器
Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法
最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验,CMS收集器是Sun HotSpot虚拟机中第一款真正意义上并发垃圾收集器以上是关于JVM垃圾回收器的主要内容,如果未能解决你的问题,请参考以下文章

JVM系列 - JVM垃圾回收器

linux怎么查看jvm正在使用的哪个垃圾回收器

JVM专题--垃圾回收算法, 垃圾回收器

JVM垃圾回收器

垃圾收集JVM的垃圾回收器有哪些特点?

JVM的垃圾回收机制 总结(垃圾收集回收算法垃圾回收器)