Hotspot垃圾回收器


HotSpot虚拟机提供了多种垃圾收集器,每种收集器都有各自的特点,没有最好的垃圾收集器,只有最适合的垃圾收集器。我们可以根据自己实际的应用需求选择最适合的垃圾收集器。根据新生代和老年代各自的特点,我们应该分别为它们选择不同的收集器,以提升垃圾回收效率。

 

一、新生代垃圾收集器

1. Serial垃圾收集器

  1. 单线程 
    只开启一条GC线程进行垃圾回收,并且在垃圾回收过程中停止一切用户线程,从而用户的请求或图形化界面会出现卡顿。

  2. 适合客户端应用 
    一般客户端应用所需内存较小,不会创建太多的对象,而且堆内存不大,因此垃圾回收时间比较短,即使在这段时间停止一切用户线程,用户也不会感受到明显的停顿,因此本垃圾收集器适合客户端应用。

  3. 简单高效 
    由于Serial收集器只有一条GC线程,因此避免了线程切换的开销,从而简单高效。

  4. 采用“复制”算法

2. ParNew垃圾收集器

ParNew是Serial的多线程版本。 
1. 多线程并行执行 
ParNew由多条GC线程并行地进行垃圾清理。但清理过程仍然需要停止一切用户线程。但由于有多条GC线程同时清理,清理速度比Serial有一定的提升。

  1. 适合多CPU的服务器环境 
    由于使用了多线程,因此适合CPU较多的服务器环境。

  2. 与Serial性能对比 
    ParNew和Serial唯一的区别就是使用了多线程进行垃圾回收,在多CPU的环境下性能比Serial会有一定程度的提升;但线程切换需要额外的开销,因此在单CPU环境中表现不如Serial。

  3. 采用“复制”算法

  4. 追求“降低停顿时间” 
    和Serial相比,ParNew使用多线程的目的就是缩短垃圾收集时间,从而减少用户线程被停顿的时间。

3. Parallel Scavenge垃圾收集器

Parallel Scavenge和ParNew一样都是多线程、新生代收集器,都使用“复制”算法进行垃圾回收。但它们有个巨大的不同点:ParNew收集器追求降低用户线程的停顿时间,因此适合交互式应用;而Parallel Scavenge追求CPU吞吐量,能够在较短的时间内完成指定任务,因此适合没有交互的后台计算。

  1. 什么是“吞吐量”? 
    吞吐量是指用户线程运行时间占CPU总时间的比例。 
    CPU总时间包括:用户线程运行时间 和 GC线程运行的时间。 
    因此,吞吐量越高表示用户线程运行时间越长,从而用户线程能够被快速处理完。

  2. 降低停顿时间的两种方式 
    1.在多CPU环境中使用多条GC线程,从而垃圾回收的时间减少,从而用户线程停顿的时间也减少; 
    2.实现GC线程与用户线程并发执行。所谓并发,就是用户线程与GC线程交替执行,从而每次停顿的时间会减少,用户感受到的停顿感降低,但线程之间不断切换意味着需要额外的开销,从而垃圾回收和用户线程的总时间将会延长。

  3. Parallel Scavenge提供的参数

    • 设置“吞吐量” 
      通过参数-XX:GCTimeRadio设置垃圾回收时间占总CPU时间的百分比。

    • 设置“停顿时间” 
      通过参数-XX:MaxGCPauseMillis设置垃圾处理过程最久停顿时间。Parallel Scavenge会根据这个值的大小确定新生代的大小。如果这个值越小,新生代就会越小,从而收集器就能以较短的时间进行一次回收。但新生代变小后,回收的频率就会提高,因此要合理控制这个值。

    • 启用自适应调节策略 
      通过命令-XX:+UseAdaptiveSizePolicy就能开启自适应策略。我们只要设置好堆的大小和MaxGCPauseMillis或GCTimeRadio,收集器会自动调整新生代的大小、Eden和Survior的比例、对象进入老年代的年龄,以最大程度上接近我们设置的MaxGCPauseMillis或GCTimeRadio。

二、老年代垃圾收集器

1. Serial Old垃圾收集器

Serial Old收集器是Serial的老年代版本,它们都是单线程收集器,也就是垃圾收集时只启动一条GC线程,因此都适合客户端应用。

它们唯一的区别就是Serial Old工作在老年代,使用“标记-整理”算法;而Serial工作在新生代,使用“复制”算法。

2. Parallel Old垃圾收集器

Parallel Old收集器是Parallel Scavenge的老年代版本,一般它们搭配使用,追求CPU吞吐量。 
它们在垃圾收集时都是由多条GC线程并行执行,并停止一切用户线程。因此,由于在垃圾清理过程中没有使垃圾收集和用户线程并行执行,因此它们是追求吞吐量的垃圾收集器。

3. CMS垃圾收集器

CMS收集器是一款追求停顿时间的老年代收集器,它在垃圾收集时使得用户线程和GC线程并行执行,因此在垃圾收集过程中用户也不会感受到明显的卡顿。但用户线程和GC线程之间不停地切换会有额外的开销,因此垃圾回收总时间就会被延长。

垃圾回收过程

  1. 初始标记 
    停止一切用户线程,仅使用一条初始标记线程对所有与GC ROOTS直接关联的对象进行标记。速度很快。
  2. 并发标记 
    使用多条并发标记线程并行执行,并与用户线程并发执行。此过程进行可达性分析,标记出所有废弃的对象。速度很慢。
  3. 重新标记 
    停止一切用户线程,并使用多条重新标记线程并行执行,将刚才并发标记过程中新出现的废弃对象标记出来。这个过程的运行时间介于初始标记和并发标记之间。
  4. 并发清除 
    只使用一条并发清除线程,和用户线程们并发执行,清除刚才标记的对象。这个过程非常耗时。

CMS的缺点

  1. 吞吐量低 
    由于CMS在垃圾收集过程使用用户线程和GC线程并行执行,从而线程切换会有额外开销,因此CPU吞吐量就不如在垃圾收集过程中停止一切用户线程的方式来的高。
  2. 无法处理浮动垃圾,导致频繁Full GC 
    由于垃圾清除过程中,用户线程和GC线程并发执行,也就是用户线程仍在执行,那么在执行过程中会产生垃圾,这些垃圾称为“浮动垃圾”。 
    如果CMS在垃圾清理过程中,用户线程需要在老年代中分配内存时发现空间不足时,就需要再次发起Full GC,而此时CMS正在进行清除工作,因此此时只能由Serial Old临时对老年代进行一次Full GC。
  3. 使用“标记-清除”算法产生碎片空间 
    由于CMS使用了“标记-清除”算法, 因此清除之后会产生大量的碎片空间,不利于空间利用率。不过CMS提供了应对策略: 
    • 开启-XX:+UseCMSCompactAtFullCollection 
      开启该参数后,每次FullGC完成后都会进行一次内存压缩整理,将零散在各处的对象整理到一块儿。但每次都整理效率不高,因此提供了以下参数。
    • 设置参数-XX:CMSFullGCsBeforeCompaction 
      本参数告诉CMS,经过了N次Full GC过后再进行一次内存整理。

三、通用垃圾收集器——G1垃圾收集器

G1是目前最牛逼的垃圾收集器。

G1的特点

  1. 追求停顿时间
  2. 多线程GC
  3. 面向服务端应用
  4. 标记-整理和复制算法合并 
    不会产生碎片内存。
  5. 可对整个堆进行垃圾回收
  6. 可预测停顿时间

G1的内存模型

G1垃圾收集器没有新生代和老年代的概念了,而是将堆划分为一块块独立的Region。当要进行垃圾收集时,首先估计每个Region中的垃圾数量,每次都从垃圾回收价值最大的Region开始回收,因此可以获得最大的回收效率。

Remembered Set

一个对象和它内部所引用的对象可能不在同一个Region中,那么当垃圾回收时,是否需要扫描整个堆内存才能完整地进行一次可达性分析?

当然不是,每个Region都有一个Remembered Set,用于记录本区域中所有对象引用的对象所在的区域,从而在进行可达性分析时,只要在GC ROOTs中再加上Remembered Set即可防止对所有堆内存的遍历。

G1垃圾收集过程

    1. 初始标记 
      标记与GC ROOTS直接关联的对象,停止所有用户线程,只启动一条初始标记线程,这个过程很快。
    2. 并发标记 
      进行全面的可达性分析,开启一条并发标记线程与用户线程并行执行。这个过程比较长。
    3. 最终标记 
      标记出并发标记过程中用户线程新产生的垃圾。停止所有用户线程,并使用多条最终标记线程并行执行。
    4. 筛选回收 
      回收废弃的对象。此时也需要停止一切用户线程,并使用多条筛选回收线程并行执行。

Hotspot垃圾回收器的更多相关文章

  1. Hotspot JVM垃圾回收器

    前两篇<JVM入门——运行时数据区><JVM常见垃圾回收算法>所提到的实际上JVM规范以及常用的垃圾回收算法,具体的JVM实现实际上不止一种,有JRockit.J9等待,当然最 ...

  2. [Inside HotSpot] Serial垃圾回收器 (二) Minor GC

    Serial垃圾回收器Minor GC 1. DefNewGeneration垃圾回收 新生代使用复制算法做垃圾回收,比老年代的标记-压缩简单很多,所有回收代码都位于DefNewGeneration: ...

  3. [Inside HotSpot] Serial垃圾回收器 (一) Full GC

    Serial垃圾回收器Full GC Serial垃圾回收器的Full GC使用标记-压缩(Mark-Compact)进行垃圾回收,该算法基于Donald E. Knuth提出的Lisp2算法,它会把 ...

  4. JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接

    原文 https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ 再插一个关于线程和进程上下文,待判断 http://b ...

  5. Java垃圾回收算法和垃圾回收器

    基本上 jvm内存回收有三种 基本算法 标记-清除 标记清除的算法最简单,主要是标记出来需要回收的对象,然后然后把这些对象在内存的信息清除.如何标记需要回收的对象,在上一篇文章里面已经有说明. 标记- ...

  6. JVM学习总结三——垃圾回收器

    整两天再看调优分析的部分,发现实际运行环境下,还是要考虑配置垃圾回收器,所以这里就加一小章介绍一下. 首先来看一下HotSpot所支持回收期的关系图: 图中可以看到一共有7中垃圾回收器,以中间绿线为界 ...

  7. Jvm垃圾回收器(终结篇)

    知识回顾: 第一篇<Jvm垃圾回收器(基础篇)>主要讲述了判断对象的生死?两种基础判断对象生死的算法.引用计数法.可达性分析算法,方法区的回收.在第二篇<Jvm垃圾回收器(算法篇)& ...

  8. Jvm垃圾回收器(算法篇)

    在<Jvm垃圾回收器(基础篇)>中我们主要学习了判断对象是否存活还是死亡?两种基础的垃圾回收算法:引用计数法.可达性分析算法.以及Java引用的4种分类:强引用.软引用.弱引用.虚引用.和 ...

  9. JVM(五)垃圾回收器的前世今生

    全文共 2195 个字,读完大约需要 8 分钟. 如果垃圾回收的算法属于内存回收的方法论的话,那本文讨论的垃圾回收器就属于内存回收的具体实现. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器 ...

随机推荐

  1. WebSocket 在烧瓶和龙卷风中的应用

    a. 安装 pip3 install gevent-websocket 作用: - 处理Http.Websocket协议的请求 -> socket - 封装Http.Websocket相关数据 ...

  2. Flask--信号 blinker

    Flask--信号 blinker Flask框架中的信号基于blinker,可以让开发者在flask请求过程中 定制一些用户行为执行. 在请求前后,模板渲染前后,上下文前后,异常 的时候 安装: p ...

  3. jquery自定义插件实现分页效果

    这节介绍如何自定义jquery插件,实现分页效果,话不多说,先看看实现的效果: 分页插件 实现的代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTM ...

  4. lzugis——Arcgis Server for JavaScript API之自定义InfoWindow(续)

    同样的标题后面加了一个括弧,不是为了增减博文数量,而确实是上个功能的完善,标注为续,意思是继续上次的内容,来说说如何自定义InfoWindow. 在上一讲中,实现了InfoWindow的显示,但是并没 ...

  5. [置顶] 【机器学习PAI实践三】雾霾成因分析

    一.背景 如果要人们评选当今最受关注话题的top10榜单,雾霾一定能够入选.如今走在北京街头,随处可见带着厚厚口罩的人在埋头前行,雾霾天气不光影响了人们的出行和娱乐,对于人们的健康也有很大危害.本文通 ...

  6. 深度学习(六十二)SqueezeNet网络设计思想笔记

  7. 从无到有开发自己的Wordpress博客主题---主页模板

    在只做完成了header和footer的模板之后,我们首先在之前Hello World的基础上做一个最简单的调用测试 //修改index.php内容如下 <?php get_header(); ...

  8. [转]优化Flash性能

    原文:http://www.adobe.com/devnet/flash/articles/optimizing-flash-performance.html 翻译:http://bbs.9ria.c ...

  9. (二)Nginx反向代理与负载均衡的实现

    引言:nginx正向代理与反向代理在上一篇文章中已经谈论过,这里狗尾草主要告诉大家Nginx对前端的小伙伴来说在工作中如何简单的使用. 1.0什么是反向代理 当我们有一个服务器集群,并且服务器集群中的 ...

  10. 在spring配置文件中的 <context:property-placeholder/>用途

    location属性为 具体配置文件的classpath:地址 (可以取配置文件中的值利用${key}的形式,而不用多次写值) 1.这样一来就可以为spring配置的bean的属性设置值了,比如spr ...