美文网首页JVM
关于GC之二-常用GC算法

关于GC之二-常用GC算法

作者: AlanKim | 来源:发表于2019-01-27 09:06 被阅读15次

回收

回收是个比较大的话题,有各种各样的算法,针对不同区域,也有不同的算法选择。

常见的GC算法

标记清除(Mark-Sweep):

最基础的GC算法,将需要回收的对象做标记,之后扫描,对标记为可清除的对象进行回收。

清理完成之后会产生随便。是CMS是基础

复制(Copying)

标准应用就是young代的两个S区,互为From、To,复制后,清除From及eden中所有空间。如果To空间不足,则需要对象晋升到Old代。

标记-整理(Mark-Compact)

实现上与标记清除算法前半段一样,都是先标记。但是在清除时,是先将标记过的不需要回收的对象移动到一起,使得内存连续,这样,只要将标记边界之外的内存空间清理掉就好了。解决了碎片化问题。

GC实现的搭配使用

关于GC的实现及搭配使用,先上一个图:

1353773614_1052.jpg

可以看到,除了G1是自己包办天下外,其他的GC算法都是新生代+老年代搭配起来用的,这跟各个分代中的对象特性有一定关系。下面详细说明:

Serial GC:
  • 顾名思义,串行GC。单线程回收机制,在做回收时,会停掉其他所有操作,即STW。
  • 适用于单CPU、新生代空间很小以及对暂停时间不是很敏感的应用上
  • 使用JVM args:-XX:+UseSerialGC 来指定使用。
  • 同样有Serial Old算法,用于老年代收集,但是会STW很久。
ParNew GC:
  • 在SerialGC的基础上加入了多线程,但是在GC的时候一样需要STW,只是GC是多个线程在同时进行而已,提高了效率。
  • 使用JVM args: -XX:+UseParNewGC来指定使用
  • 只在Young代收集
Parallel Scavenge:
  • 在扫描和复制过程采用多线程,与parNew很类似,但是侧重点不同。
  • parNew主要侧重于停顿时间尽量少,不至于使用户一直等待。而parallel scavenge则侧重于达到一个可控制的吞吐量(Throughput)。也被称为吞吐量优先收集器。
  • 所谓吞吐量就是CPU用于运行用户代码时间与CPU总消耗时间的比值。吞吐量=运行用户代码时间/运行用户代码时间+垃圾收集时间。
  • 使用JVM args: -XX:+UseParallelGC来指定使用
  • 使用JVM args: -XX:ParallelGCThreads=4 来指定线程数
  • 对应的Parallel Old GC 用于老年代收集
CMS
  • Concurrent Mark Sweep
  • 目标是为了解决Serial GC的停顿问题,达到最短回收时间。
  • 从其缩写可以看到,基于Mark-Sweep算法实现的,当然也就会有碎片化问题。
  • 整个收集过程分为以下五个大步骤:
    • 初始化标记,CMS initial mark,标记GC Roots能直接关联到的对象,需要STW,执行速度很快
    • 并发标记,CMS concurrent mark,进行GC Roots Tracing,一条条链路直到叶子节点,并发执行,不影响业务。
    • 重新标记,CMS remark,修正并发标记执行中,线程继续执行产生的标记变化,需STW,比初始化标记时间久,但是远小于并发标记耗时。
    • 并发清除,CMS concurrent sweep,根据标记执行并发清除,不需要STW。
    • 并发reset,恢复初始化设置,不需要stw,耗时非常短
  • CMS缺点
    • 对CPU资源非常敏感,在并发阶段,虽然不会导致用户线程停顿,但是会占用cpu资源,从而导致应用变慢,总吞吐量下降。
    • 默认的回收线程数是: (cpu-kernel-count + 3)/ 4。也就是说,四核cpu,那么就是 (4+3)/4 = 1(取整)
    • 无法处理浮动垃圾
    • 由于GC过程中,用户线程继续在执行,所以要预留足够的内存空间给用户线程使用。因此CMS不能像其他GC收集器那样等到老年代快被填满了再进行收集,需要预留一部分空间,默认在Old代 68%的空间被使用时就会触发CMS。
    • 可以使用JVM args: -XX:CMSInitiatingOccupancyFraction来指定触发CMS的百分比,比如提高百分比,减少CMS GC触发的次数,提高性能。该参数必须配合-XX:UseCMSInitiatingOccupancyOnly使用才有效
    • 但是如果预留的内存太少,无法满足应用运行的内存需要,那么就会出现Concurrent Mode Failure 异常
    • 出现Concurrent Mode Failure时,JVM会临时启用Serial Old GC,来重新进行Old代的收集,这样STW时间就会很长。
    • 基于Mark-Sweep,会产生很多碎片。在有大对象需要分配空间时,内存无法找到连续空间来分配,不得不提前偿触发一次Full GC。
    • 使用JVM args: -XX:UseCMSCompactAtFullCollection在Full GC之后增加一个压缩过程
    • 使用JVM args: -XX:CMSFullGCBeforeCompaction=? 参数设置执行多少次不需要压缩的CMS Full GC后,进行一次压缩操作
  • 浮动垃圾 floating garbage:并发清理阶段产生的garbage,本次gc已经无法处理,只能等待下次处理。
  • GC Roots:
    • 虚拟机栈(栈帧中局部变量表)中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • Native Method Stack中JNI中引用的对象。
G1

基于标记整理,Mark-Compact,不会产生内存碎片。

分region,region维度进行GC,而不是在young、old、方法区整个维度进行整理。

相关文章

  • 关于GC之二-常用GC算法

    回收 回收是个比较大的话题,有各种各样的算法,针对不同区域,也有不同的算法选择。 常见的GC算法 标记清除(Mar...

  • GC常用算法及常见分代:Minor GC、Major GC和Fu

    GC常用算法及常见分代:Minor GC、Major GC和Full GC [TOC] GC的概念在20世纪60年...

  • gc常用算法

    标记清除 标记清除主要分为两步 标记,标记需要清除的对象 清除,在内存中清除这些对象 优点 速度快 清理之后存活对...

  • 【JVM】垃圾回收机制(1)--如何判定对象可以回收

    一 垃圾回收机制概述 也没有规定GC如何工作。不过常用的jvm都有GC,而且大多数GC都使用类似的算法管理内存和执...

  • chapter-4 GC算法与种类

    GC 算法与种类 ■ GC的概念■ GC算法• 引用计数法• 标记清除• 标记压缩• 复制算法■可触及性■ Sto...

  • GC算法基础

    英文原文:GC Algorithms: Basics译者:有孚译文地址:GC算法基础 在深入GC算法的实现细节之前...

  • Lua GC

    一、GC的原理及其算法设计 不同的语言,对GC算法的设计不同,常见的GC算法是引用计数和Mark-Sweep算法,...

  • 通过 gc.log 调优 JVM

    一、GC 日志查看 GC 日志默认是关闭的,需要查看 GC 日志首先需要开启 GC 日志。 常用 GC 日志的配置...

  • 深入理解JVM(二)

    GC详解 GC的作用域 GC的作用域如下图所示。 关于垃圾回收,只需要记住 ,即不同的区域使用不同的算法。 不同区...

  • HotSpot note (part-3)

    part 3 DefNew的GC属于Minor GC,使用copying算法进行垃圾收集,是Serial GC(-...

网友评论

    本文标题:关于GC之二-常用GC算法

    本文链接:https://www.haomeiwen.com/subject/idhjjqtx.html