Java虚拟机有很多垃圾收集器

下面先来了解HotSpot虚拟机中的7种垃圾收集器:Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1,先介绍一些垃圾收集的相关概念,再介绍它们的主要特点、应用场景、以及一些设置参数和基本运行原理。

常见的垃圾收集器关系图如下:

如果两个收集器直接有连线,则表示可以搭配使用,而G1收集器是不区分老年代和新生代的,所以不需要和其他收集器搭配,其他的则只能用于老年代或是新生代。

下面针对每个收集器逐个分析:

1.Serial收集器(新生代收集器)

Serial是历史最悠久的收集器,也一个单线程收集器,只有一个CPU或一个线程来完成垃圾收集工作,而且Serial收集器在垃圾回收的时候会暂停所有工作线程,直到垃圾回收结束再恢复工作线程。

2.ParNew收集器(新生代收集器)

ParNew收集器是Serial收集器的多线程版本,工作方式和工作原理完全一致,只是ParNew收集器会创建多个线程来进行垃圾回收工作。不过如果是在单CPU的情况下,ParNew收集器的性能反而不一定有Serial收集器好,因为ParNew还有额外的线程之间切换的消耗,如果是多CPU的情况下,则效果更好点,所以ParNew默认开启的垃圾收集的线程个数一个和CPU的数量是1:1的比例,在线程数比CPU数量小的情况下,ParNew的性能还是很可观的。

3.Parallel Scavenge收集器(新生代收集器)

Parallel Scavenage收集器是采用了复制算法,且是并行的多线程收集器,它的特点是不关注收集器用户线程的停顿时间,而是关注达到一个可控制的吞吐量。吞吐量为CPU用于运行用户线程的代码与CPU总耗时的比例,比如JVM工作100分钟,垃圾回收使用1分钟,用户线程使用99分钟,则吞吐量就是99%,Paramllel Scavenge收集器提供两个参数用户控制吞吐量。分别是控制最大垃圾收集停顿时间 -XX:MaxGCPauseMillis参数、设置吞吐量大小-XX:GCTimeRatio

如果设置停顿时间过短,则垃圾收集时花费的时间不会超过最大值,但是如果停顿时间过于小,就会导致新生代的垃圾回收的频率会增高,本来可以10秒收集一次,停顿100毫秒,变成了5秒收集一次,每次停顿70毫秒,虽然停顿时间降低了,但是整体的吞吐量却下降了。

而如果直接设置吞吐量,则收集器会按照吞吐量设置的值来分配整体的垃圾收集的时间来进行收集垃圾。

4.Serial Old收集器(老年代收集器)

Serial Old是Serial收集器的老年代版本,也是单线程的,使用的“标记-整理”算法

5.Parallel Old收集器(老年代收集器)

Parallel Old是Paraller Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法,只能与Parallel Scavenge收集器搭配使用

6.CMS收集器(老年代收集器)

CMS是目前最常用的收集器,主要是和ParNew来搭配使用。CMS(Concurrent  Mark Sweep)从名字可以看出是并发的标记清除垃圾收集器,过程比较复杂。特点是以获取最短回收停顿时间为目标,整个过程大致分为四个步骤:

初始标记-》并发标记-》并发预处理-》重新标记-》并发清除

初始标记:标记一下GC Roots能够关联到的对象,速度很快,但是也会使用户线程短暂的停止,只是停顿的时间很快。

并发标记:并发标记耗时较长,但是可以和用户线程并发进行,不需要使用户暂停,不过会消耗CPU的资源,会影响到用户线程的吞吐量,CMS默认会开启回收线程的数量是CPU个数+3/4,比如cpu是1的情况下,会启动一个线程,如果cpu是5的话,就会启动2个线程,并发标记会根据初始标记出来的通过GC ROOTS关联到的对象,然后通过递归继续标记这些对象可以达到的对象

重新标记:暂停用户线程,重新在堆中进行可达性分析,标记存货对象,此时的存活又没有被标记的对象很少了,所以用户线程停顿的时间也较短

并发清除:和用户线程并发进行,清除没有被标记的对象

另外CMS收集器无法处理浮动垃圾,因为cms和用户线程是并发进行的,在垃圾回收的同时用户线程可能会产生新的垃圾,这就使得本次垃圾回收无法清除,会留到下一次回收。另外cms是和用户线程并行处理的,所以在工作时还需要预留足够的内存空间在用户线程使用,因此cms收集器不能像其他收集器一样等到老年代几乎满了才开始进行垃圾回收,需要预留一部分给用户线程使用,默认情况下在老年代使用了68%空间之后就会触发垃圾回收。当然也可以通过设置jvm参数-XX:CMSInitatingOccupancyFraction来设置触发的百分比。

而如果CMS没有预留足够空间给用户线程的话,会出现“Concurrent Mode Failure”失败,这是虚拟机就会启动预备方案,临时启用Serial Old收集器来重新对老年代进行一次垃圾收集,这样就会影响性能。

而且由于CMS是通过标记清除算法,所以会产生大量的内存碎片,就会出现老年代内存空间足够但是无法创建一些大对象,就会提前触发一次Full GC。而CMS就提供了两个JVM参数用来优化这个问题,分别是:

-XX:+UseCMSCompactAtFullCollect参数,使得在实现Full GC之后额外进行一次内存整理,这样就没有了内存碎片,但是涉及到内存整理,所以停顿时间变长了

-XX:CMSFullGCsBeforeCompaction参数,设置在执行多少次不压缩的Full GC之后进行一次内存整理。

7.G1收集器  (新生代、老年代收集器)

G1收集器没有新生代和老年代的区分,G1实现了不牺牲吞吐量的情况下又达到了低停顿的效果。主要是因为G1不像其他收集器一样针对整个新生代或是老年代进行垃圾回收,而且将整个堆内存划分成了多个大小一样的独立区域,并跟踪每个区域的垃圾情况,并且有一个优先列表,优先回收垃圾最多的区域。

JVM探秘4---垃圾收集器介绍的更多相关文章

  1. JVM探秘:垃圾收集器

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. 垃圾收集器 垃圾收集算法是是内存回收的方法论,垃圾收集器是内存回收的具体实现.不同的虚 ...

  2. jvm七种垃圾收集器

    JVM_七种垃圾收集器介绍   本文中的垃圾收集器研究背景为:HotSpot+JDK7 一.垃圾收集器概述 如上图所示,垃圾回收算法一共有7个,3个属于年轻代.三个属于年老代,G1属于横跨年轻代和年老 ...

  3. 【JVM】JVM中的垃圾收集器

    垃圾收集器组合 Serial+Serial Old Serial+CMS ParNew+CMS ParNew+Serial Old Paralle Scavenge + Serial Old Para ...

  4. JVM垃圾收集器介绍

    垃圾回收算法是GC的方法论,垃圾收集器就是内存回收的具体实现. 一.Serial 收集器 单线程收集器,在进行GC时,必须暂停所有的工作线程(Stop The World),直到GC收集结束. 缺点: ...

  5. jvm系列 (二) ---垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...

  6. JVM学习记录-垃圾收集器

    先回顾一下上一篇介绍的JVM中常见几种垃圾收集算法: 标记-清除算法(Mark-Sweep). 复制算法(Copying). 标记整理算法(Mark-Compact). 分代收集算法(Generati ...

  7. 【JVM.2】垃圾收集器与内存分配策略

    垃圾收集器需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 在前一节中介绍了java内存运行时区域的各个部分,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈 ...

  8. 通过jmap查看jvm采用的垃圾收集器

    1  tomcat 的PID获得 ps -ef|grep tomcat [root@iZ2zeapch8kbaw4bxnz8vxZ tomcat7]# ps -ef|grep tomcat root ...

  9. 💕《给产品经理讲JVM》:垃圾收集器

    前言 在上篇中,我们把 JVM 中的垃圾收集算法有了一个大概的了解,又是一个阴雨连绵的周末,宅在家里的我们又开始了新一轮的学习: 产品大大:上周末我们说了垃圾收集算法,下面是不是要讲一下这些算法的应用 ...

  10. JVM_七种垃圾收集器介绍

    本文中的垃圾收集器研究背景为:HotSpot+JDK7 一.垃圾收集器概述 如上图所示,垃圾回收算法一共有7个,3个属于年轻代.三个属于年老代,G1属于横跨年轻代和年老代的算法. JVM会从年轻代和年 ...

随机推荐

  1. 为什么mysql 5.7.24启停不显示错误信息?log-error_verbosity参数

    关键词:log-error_verbosity ,mysql启停没有信息,mysql启停不显示错误信息,mysql不显示启停信息 原因就是因为 log-error_verbosity = 2 被设置成 ...

  2. ansible的安装及基本使用

    1.安装ansible 如果没有版本和别的要求,这里直接使用yum安装 yum -y install ansible 查看版本 [root@ ~]#ansible --version ansible ...

  3. sublime使用手册

    1.怎么批量选中开头和结尾?将光标定位到区域的开头,ctrl+alt+下键(一直按下键). 2.怎么打开和关闭tab的自动补全?preferences->settings->User{ & ...

  4. 常见的local variable 'x' referenced before assignment问题

    def fun1(): x = 5 def fun2(): x *= 2 return x return fun2() 如上代码,调用fun1() 运行会出错:UnboundLocalError: l ...

  5. field-symbols: <ATTR> type ANY.

    field-symbols: type ANY. * importing iv_root_list type refer to if_genil_cont_root_objectlist DATA l ...

  6. 122A

    Copy #include <stdio.h> int main() { int dig; int flag=0; scanf("%d", &dig); if( ...

  7. syslog-ng内容讲解

    一.基础syslog-ng作为syslog的替代工具,可以完全替代syslog的服务,并且通过定义规则,实现更好的过滤功能.系统自带版本: 引用 # rpm -qa|grep syslog-ngsys ...

  8. [LeetCode] 434. Number of Segments in a String_Easy

    Count the number of segments in a string, where a segment is defined to be a contiguous sequence of ...

  9. Express web框架 upload file

    哈哈,敢开源,还是要有两把刷子的啊 今天,看看node.js 的web框架 Express的实际应用 //demo1 upload file <html><head><t ...

  10. python快速开发Web之Django

    以前写测试框架,要么是纯python代码驱动的,要么是WinForm界面的框架,多人操作并不适合. 就想用python写个Web版的,于是想到了Web快速开发的框架Flask和Django两个 个人觉 ...