【jvm】垃圾收集器

在了解垃圾收集算法以后,咱们要看一下基于垃圾收集算法实现的垃圾收集器是如何实现的,本文出现的垃圾收集器都是HotSpot虚拟机提供的实现html

堆内存是垃圾收集器主要回收垃圾对象的地方,堆内存能够根据对象生命周期的不一样细分为新生代和老年代,每一个年代均可以选择适合的垃圾收集算法,新生代使用复制算法,老年代使用标记清除或者标记整理算法java

HotSpot虚拟机提供了7种垃圾收集器,其中适用于新生代的三种,老年代的三种,还有一种新生代老年代都适用算法

新生代垃圾收集器:Serial收集器,ParNew收集器,Parallel Scavenge收集器多线程

老年代垃圾收集器:Serial Old收集器,Parallel Old收集器,CMS收集器并发

都适用的收集器:G1收集器jvm

全部垃圾收集器组合状况以下:性能

图中连线的收集器代表能够一块儿搭配使用线程

Serial 收集器

Serial收集器曾是jdk1.3以前新生代收集器的惟一选择,串行收集器,单线程工做,因此效率高,可是会产生Stop The World,适用于堆内存比较小的时候使用,使用复制算法回收垃圾对象3d

参数设置:-XX:+UseSerialGC 使用Serial收集器cdn

ParNew 收集器

parNew收集器是Serial收集器的多线程版本,并行收集器,除了多线程收集外,其他功能与Serial收集器基本一致,在新生代中,除了Serial收集器,只有ParNew收集器能够与CMS收集器一块儿使用,因此目前为止这个收集器是新生代最经常使用的收集器

参数设置:

  • -XX:+UseParNewGC:使用ParNew收集器
  • -XX:ParallelGCThreads:用来限制垃圾收集的线程数

Parallel Scavenge 收集器

并行收集器,一样使用复制算法,与其他两种年轻代收集器不一样的地方在于它的关注点,Serial和ParNew收集器的关注点在于尽量的缩短Stop The World的时间,而Parallel Scavenge收集器的关注点在于吞吐量

吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),好比虚拟机运行100分钟,垃圾收集时间是1分钟,那么吞吐量就是99%

参数设置:

  • -XX:+UseParallelGC:使用Parallel收集器
  • -XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间
  • -XX:GCTimeRatio:设置吞吐量大小,默认为99,容许1%的垃圾收集时间
  • -XX:+UseAdaptiveSizePolicy:自适应调节,设置以后就不须要手动设置新生代大小

Serial Old 收集器

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

能够与Parallel Scavenge收集器搭配使用,也能够做为CMS收集器发生Concurrent Mode Failure时老年代的备选方案使用

Parallel Old 收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用标记整理算法

在注重吞吐量及CPU资源敏感的场景,能够用考虑使用Parallel Scavenge+Parallel Old收集器

参数设置:-XX:+UseParallelOldGC:使用Parallel Scavenge + Parallel Old收集器

CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,目前使用最多的垃圾收集器,使用这类收集器的应用重视服务的响应速度,但愿系统停顿时间最短,以给用户带来较好的体验

使用标记清除算法,共4个步骤

  1. 初始标记(CMS initial mark)
  2. 并发标记(CMS concurrent mark)
  3. 从新标记(CMS remark)
  4. 并发清除(CMS concurrent sweep)

初始标记、从新标记这两个步骤仍然须要Stop The World,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而从新标记阶段则是为了修正并发标记期间,因用户程序继续运做而致使标记产生变更的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但远比并发标记的时间短

耗时较长的并发标记和并发清除的线程能够与用户线程一块儿工做,因此整体上来讲,CMS收集器的内存回收过程是与用户线程一块儿并发地执行

优势:并发收集,低停顿

缺点:

  1. 对CPU资源敏感

    CMS默认启动的回收线程数量是(CPU数量+3)/4,当CPU数量小于4时,并发操做时会占用一半的CPU去进行垃圾收集

  2. 没法处理浮动垃圾,可能回致使Concurrent Mode Failure失败而致使领一次Full GC的产生

    CMS收集器触发GC时须要预留一部分空间供并发收集时使用,经过设置参数-XX:CMSInitiatingOccupancyFraction的值来提升触发的百分比

    当预留的空间没法知足需求时就会发生Concurrent Mode Failure失败,这时,java虚拟机就会采用Serial Old收集器回收老年代垃圾,代价就是停顿时间变长

    因此-XX:CMSInitiatingOccupancyFraction参数设置的太高容易频繁触发Concurrent Mode Failure失败,致使性能下降

  3. 产生大量空间碎片

    设置-XX:+ UseCMSCompactAtFullCollection参数,开启空间压碎,默认是开启的,开启后FUll GC时会进行内存整理,空间碎片问题解决,可是停顿时间就会变长

    设置-XX:+ CMSFullGCsBeforeCompaction参数,设置进行几回Full GC后,进行一次碎片整理,默认是0,表示每次进入Full GC时都进行碎片整理

参数设置:

  • -XX:+UseConcMarkSweepGC:使用CMS收集器 + PerNew收集器
  • -XX:ParallelCMSThreads:设定CMS的线程数量

G1 收集器

G1是一款面向服务端应用的垃圾收集器,HotSpot开发团队赋予它的使命是将来能够替换掉JDK1.5中发布的CMS收集器

G1收集器采用标记整理算法,因此G1收集器不会产生空间碎片

G1特色:

  • 并行与并发

    G1能够充分的利用多CPU和多核环境下的硬件优点用来缩短Stop The World的停顿时间

  • 可预测的停顿

    下降停顿时间是G1和CMS的共同关注点,但G1除了追求低停顿外,还能创建可预测的停顿时间模型,能让使用者明确指定在一个长度为N毫秒的时间片断内,消耗在垃圾收集上的时间不得超过N毫秒,这几乎已是实时Java(RTSJ)的垃圾收集器的特征了

G1收集器将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代再也不是物理隔阂了,它们都是一部分(能够不连续)Region的集合

G1的新生代收集跟ParNew相似,当新生代占用达到必定比例的时候,开始出发收集;和CMS相似,G1收集器收集老年代对象会有短暂停顿

收集步骤:

  1. 初始标记

    标记一下GC Roots能直接关联到的对象

  2. 并发标记

    从GC Roots出发,开始对堆中对象进行可达性分析,找出存活对象

  3. 最终标记

    为了修正并发标记阶段因用户程序继续运行而致使标记产生变更的那一部分标记记录

  4. 筛选回收

    对各个Region的回收价值和成本进行排序,根据用户所期待的GC停顿时间来制定回收计划

参考: jvm系列(三):java GC算法 垃圾收集器

深刻理解java虚拟机第二版

更多阅读:chenmingyu.top/categories/

相关文章
相关标签/搜索