JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

垃圾回收器

GC分类与性能指标

GC分类

  • 按线程数分,可以分为串行垃圾回收器和并行垃圾回收器
    • 串行回收值的是在 同一时间段内只允许有一个CPU用于执行垃圾回收操作,此时工作线程被暂停,直至垃圾收集器结束
      • 在诸如单CPU处理器或者较小的应用内存等硬件不是特别优越的场合,串行回收器的性能表现可以超过并行回收器和并发回收器。所以,串行回收默认被应用在Client模式下的JVM中
      • 在并发能力较强的CPU上,并行回收器产生的停顿时间要短于串行回收器
    • 和串行回收器相反,并行收集可以运用多个CPU同时执行垃圾回收,因此提升了应用的吞吐量,不过并行回收仍然与串行回收一样采用独占式,使用STW机制
  • 按工作模式分,可以分为并发式垃圾回收器和独占式垃圾回收器
    • 并发式垃圾回收器与应用程序线程交替工作,以尽可能减少应用程序的停顿时间
    • 独占式垃圾回收器一旦运行,就停止应用程序中的所有线程,知道垃圾回收过程完毕
  • 按碎片处理方式分,可以分为压缩式垃圾回收器和非压缩式垃圾回收器
    • 压缩式垃圾回收器会在回收完后,对存活对象进行压缩整理,消除回收后的碎片
    • 非压缩式的垃圾回收器不进行这步操作
  • 按工作的内存区间分,分为年轻代垃圾回收器和老年代垃圾回收器

性能指标

  • 吞吐量:运行用户代码的时间占总运行时间的比例

    • 总运行时间=程序运行时间+垃圾回收时间
    • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析
  • 垃圾收集开销:吞吐量的补数,垃圾收集所用时间由于总运行时间的比例

  • 暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间

  • 收集频率:相对于应用程序的执行,收集操作发生的频率

  • 内存占用:Java堆区所占的内存大小

  • 快速:一个对象从诞生到被回收所经历的时间

  • 最主要的两点:吞吐量、暂停时间;吞吐量、暂停时间、内存占用三者是比较重要的几点

  • 吞吐量优先-》垃圾回收时间短 高响应,低延迟-》暂停时间优先-》暂停时间短

JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

现在标准:在最大吞吐量的情况下,降低停顿时间

不同垃圾回收器的概述

  • 常见的垃圾回收器

    • 串行回收器:Serial、Serial Old
    • 并行回收器:ParNew、Parallel Scavenge、Parallel Old
    • 并发回收器:CMS、G1
  • 垃圾分代

    • 新生代收集器:Serial、ParNew、Parallel Scavenge
    • 老年代收集器:Serial Old、CMS、Parallel Old
    • 整堆收集器:G1

    JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

    • 搭配方案和解释
      • JDK8之前:Serial GC可以与CMS、Serial Old组合使用;ParNew可以和CMS、Serial Old组合使用;Parallel Scavenge 可以和Serial Old、Parallel Old组合使用;
      • CMS和Serial Old直接是一个备选关系,当CMS在并发执行垃圾回收时,存在垃圾回收失败的情况,此时需要Serial Old进行垃圾回收
      • JDK8时,Serial GC与CMS;ParNew和Serial Old的组合关系废弃
      • JDK9时,Serial GC与CMS;ParNew和Serial Old的组合关系彻底删除
      • JDK14时,Parallel Scavenge与Parallel Old的组合弃用,并删除CMS
  • 查看默认垃圾回收器

    • -XX:+PrintCommandLineFlags 查看命令行相关参数
    • jinfo -flag 相关垃圾回收器参数 进程ID

Serial回收器:串行回收

  • 是最基本、历史最悠久的垃圾收集器,在JDK1.3之前新生代的唯一选择
  • 作为Hotspot中Client模式下默认新生代收集器
  • 采用复制算法、串行回收和STW执行垃圾回收
  • 提供Serial Old进行老年代垃圾回收,Serial Old同样采用串行回收和STW机制,但是算法使用标记-压缩算法
    • Serial Old是Hotspot中Client模式下默认老年代收集器
    • 在Server模式下 有两种用途
      • 与新生代的Parallel Scavenge配合使用
      • 作为老年代CMS的后备垃圾收集方案

JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • 是一个单线程收集器,单线程是指-》不仅仅只是使用一个CPU或一条收集线程去完成垃圾收集工作,最重要的是进行垃圾收集时必须暂停其他所有线程,直到回收完成
  • 优势:
    • 简单而高效(与其他单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率
  • 在用户桌面应用场景中,可用内存一般不大(几十MB至一二百MB),可以在较短时间内完成垃圾收集(几十MS至一百多MS),只要不频繁发生,使用串行收集器是可以接收的
  • 在Hotspot虚拟机中,使用-XX:+UseSerialGC可以指定新生代使用Serial收集器、老年代使用Serial Old收集器

ParNew回收器:并行回收

  • 可以说是Serial收集器的多线程版本

  • 除了采用并行回收的方式执行垃圾回收之外,还是采用复制算法和STW机制

  • 是很多JVM在Server模式下新生代的默认使用

    JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • 对新生代,回收次数频繁,使用并行方式高效

  • 对老年代,回收次数少,使用串行节省资源(节省了切换线程消耗的资源)

  • 由于ParNew是基于并行回收,是否可以断定ParNew的回收效率在任何场景下都比Serial高?

    • ParNew在多CPU环境下,可以更快速的完成垃圾收集,提升程序的吞吐量
    • 但在单个CPU时,并不比Serial更高效,因为Serial不需要CPU频繁的做任务切换,可以有效避免多线程交互过程中产生的一些额外开销
  • 出Serial外只有ParNew能与CMS做配合

  • 使用-XX:+UseParNewGC使用ParNew收集器,只涉及新生代,不涉及老年代

  • 使用-XX:ParallelGCThreads设置线程数量,默认开启与CPU个数相同的线程数

Parallel回收器:吞吐量有限

  • Hotspot年轻代中除了有ParNew是基于并行回收之外,Parallel Scavenge也是复制算法+并行回收+STW
  • 和ParNew不同,Parallel Scavenge的目标是达到一个可控制的吞吐量,即吞吐量优先
  • 自适应调节策略也是PS和ParNew的一个 重要区别
  • 高吞吐量可以高效利用CPU时间,尽快完成程序的运算任务,主要适合在后天运算而不需要 太多的交互的任务,因此常见在服务器环境中使用,例如执行批量处理,订单处理,工资支付,科学技术的应用程序
  • Parallel在JDK1.6提供了用于执行在老年代的垃圾收集器Parallel Old,用来替代Serial Old
  • Parallel Old 是 标记-压缩算法+并行回收+STW机制

JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • 在程序吞吐量有限的场景中,Parallel和Parallel Old在Server模式下性能很不错
  • JDK8中 默认使用此收集器
  • -XX:+UseParallelGC 指定使用Parallel收集器
  • -XX:+UseParallelOldGC 指定使用Parallel Old
    • 与上面一行分别适用于新生代和老年代
    • 默认一个开启后另外一个也开启(相互**)
  • -XX:ParallelGCThreads设置线程数量
    • 一般最好和CPU数相等,避免过多线程影响垃圾收集器性能
    • 在默认情况下,当CPU数量小于8时,XX:ParallelGCThreads的值等于CPU数量
    • CPU个数大于8时,XX:ParallelGCThreads值等于3+[5*CPU_count]/8
  • -XX:MaxGCPauseMills, 垃圾收集器最大停顿时间即 STW时间(毫秒)
    • 为了尽可能把停顿时间控制在MaxGCPauseMills以内,收集器在 工作时会 自动调整java堆大小或者其他一些参数
    • 对于用户来讲,停顿时间越短体验越好,但是在服务端注重高并发,整体的吞吐量,所以服务端适合Parallel
    • 使用此参数需小心
  • -XX:GCTimeRatio, 设置垃圾收集器时间占总时间的比例(=1/n+1), 用于衡量 吞吐量大小
    • 取值范围0~100,默认99,也就是垃圾回收时间不超过1%
    • 与上一个参数 有一定矛盾性,暂停时间越长,Radio参数就容易超过设定的比例
  • -XX:+UseAdaptiveSizePolicy,使用自适用调节策略
    • 这种模式下,年轻代大小、Eden和Servivor比例,晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间的平衡点
    • 在手动调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量和停顿时间,让虚拟机自己完成调优工作

CMS回收器:低延迟

  • 第一款真正意义上的并发收集器,第一次实现了让收集器与用户线程一起工作
  • 关注点是尽可能快的缩短垃圾收集时用户线程的停顿时间,停顿时间越短,就越适合与用户交互的程序,
    • 目前很大一部的java应用集中在互联网或者B/S系统的服务端上,这类引用尤其重视服务的响应速度,希望系统停顿时间最短,
  • CMS采用标记-清除算法,STW机制

JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • CMS收集器整个过程分为四个阶段:
    • 初始标记阶段
      • 这个阶段中,程序所有的工作线程都将会因为STW出现短暂的暂停,这个阶段的主要任务仅仅只是标记出GC Roots能直接关联到的对象,一旦标记完成后就会恢复之前被暂停的所有用户线程,由于直接关联对象比较少,所以这里的速度非常快
    • 并发标记阶段
      • 从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长,但是不用暂停用户线程,可以与垃圾收集器一起并发运行
    • 重新标记阶段
      • 由于在并发阶段中,程序的工作线程回合垃圾 回收器同时运行或交叉运行,因此为了修正并发标记阶段,因程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段长一些,但也远比并发标记阶段的时间短
    • 并发清除阶段
      • 此阶段清理删除掉标记阶段判断的已经死亡的对象,释放内存空间,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的
  • 尽管CMS采用的是并发回收,但是在初始化标记和重新标记阶段仍然需要STW,因此可以说明目前所有的垃圾收集器都做不到完全不需要STW,只是尽可能的缩短时间
  • 由于最耗费时间的并发标记与并发清除都不需要STW,因此整体的回收 是低停顿的
  • 另外由于垃圾收集器阶段用户线程没有停顿,所以在CMS回收过程中,还应该确保应用程序用户线程有足够可用的内存,因此CMS收集器不能像其他收集器那样等到老年代机会被填满了再进行收集,而是当堆内存使用率达到一定阈值时,便开始进行回收,确保CMS运行期间有足够的内存空间支持程序运行,要是CMS运行期间内存不足,就会出现“Concurrent Mode Failure”,这时,JVM就会启用后备方案,临时使用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了
  • CMS采用的是标记清除算法,这意味着每次执行完内存回收后,由于被执行内存回收的无用对象所占用的内存空间极有可能是不连续的一些内存块,不可避免的会产生一些内存碎片,那么CMS在为新对象分配内存时,就无法使用指针碰撞的方式,而只能使用空闲列表执行内存分配
  • 为什么不换成标记-压缩算法
    • 如果使用标记-压缩算法,那么CMS在并发清理时将会更改某些对象地址以保证内存使用空间的连续,但此时用户线程仍在执行,其使用对象的地址被更改了,极有可能造成程序崩溃,所以标记-压缩算法更适合在STW的场景下使用
  • 优点:低延迟、并发收集
  • 缺点:
    • 会产生内存碎片:导致并发清除后,用户线程的可用空间不足,在无法分配大对象的情况下,提前触发Full GC
    • 对CPU资源极其敏感:在并发阶段,虽然不会STW,但是由于占了一部分线程导致应用程序降低,总吞吐量会降低
    • 无法处理浮动的垃圾:可能出现“Concurrent Mode Failure”,导致另外一次Full GC的产生,由于程序的工作线程和回收器的清除线程是同时运行的,那么在并发标记阶段如果产生新的垃圾对象,将无法对其进行标记,导致这些新的垃圾对象无法及时清除,从而只能在下一次GC时释放这些之前未被回收的对象
  • 参数设置
    • -XX:+UseConcMarkSweepGC , 启用CMSGC
      • 会自动将-XX:+UseParNewGC打开,形成ParNew+CMS+Serial Old组合
    • -XX:CMSInitiatingOccupanyFraction 设置堆内存使用率阈值,一旦达到该阈值,便开始进行回收
      • JDK5及以前默认阈值68%,JDK6以上默认92%
      • 如果内存增长很慢,可以设定一个较大的阈值,大的阈值可以有效降低CMS的触发频率,减少老年代回收的次数可以较为明显的改善应用程序性能,反之如果应用程序内存使用率增长很快,则应该降低这个阈值,避免频发触发Serial Old收集器,
    • -XX:+UseCMSCompactAtFullCollection用于指定在执行完Full GC后对内存空间进行压缩整理,以此避免内存碎片的产生,不过由于内存压缩整理过程无法并发执行,所带来的问题就是停顿时间边长了,
    • -XX:CMSFullFCsBeforeCompaction,设置执行多少次FullGC后进行压缩整理
    • -XX:ParallelCMSThreads 设置CMS的线程数量
      • 默认启动的线程数是(:ParallelGCThreads+3)/4,:ParallelGCThreads是年轻代并行收集器的线程数,当CPU资源比较紧张时,受到CMS收集器线程的影响,应用程序的性能在垃圾回收阶段可能会非常糟糕

G1回收器:区域化分代式

为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间,同时兼顾良好的吞吐量

目标是在延迟可控的情况下获得尽可能高的吞吐量

  • 为什么叫做Garbage First

    • G1是一个并行回收器,把内存分割为很多不相关的区域(物理上不连续的),使用不同的Region来表示Eden,S0,S1,老年代等
    • G1 GC有计划的避免在整个java堆区中进行整堆收集,G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小,以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region
    • 由于这种方式的侧重点在于回收垃圾最大量的区间,所以我们起名叫垃圾优先即 Garbage First
  • 优势:

    • 并行与并发
      • 并行性:G1在回收期间,可以有多个 线程同时工作,有效利用多核计算能力,此时用户线程STW
      • 并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段发生完全阻塞应用程序的情况
    • 分代收集
      • 从分代上看,G1依然属于分代性垃圾回收期,会区分新生代与老年代,年轻代依然有Eden和s0,s1区,但从堆结构来看,它不要求整个Eden区,年轻代,老年代都是连续的,也不再坚持固定大小和固定数量
      • 将堆空间分为若干个区域,这些区域中包含了逻辑上的年轻代和老年代,
      • 和之前的各类回收器不同,它同时兼顾年轻代和老年代,对比其他回收器,或者工作在新生代,或者工作在老年代
    • 空间整合
      • CMS 标记-清除算法,内存碎片,若干次GC后进行一次整理
      • G1将内存划分为一个个的区域,内存回收是以region作为基本单位的 ,Region之间是复制算法,但整体上可以看做是标记-压缩算法,两种算法都可以避免内存碎片,这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间 而提前触发下一次GC,尤其是当java堆非常大的时候,G1的优势更加明显
    • 可预测的停顿时间模型 即 软实时
      • G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定一个在 长度 为M毫秒的时间片段内,消耗在垃圾收集上的时间不能超过N毫秒
      • 由于分区的原因,G1可以只选取部分区域进行内存回收,这样缩小了回收的范围,因此对于全局停顿情况的发生也能得到较好的 控制
      • G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小,以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region,保证了G1收集器在有限的 时间内可以获取尽可能高的收集效率
      • 相比于CMS,G1未必能做到CMS最好情况下的低延时,但是最差的情况要好很多
  • 缺点

    • 相较于CMS,G1还不具备全方位、压倒性优势,比如在用户程序运行过程中,G1无论是为了垃圾收集产生的内存占用还是程序运行时的额外执行负载都要比CMS要高
    • 从经验上来说,在小内存应用上CMS的表现大概率会优于G1,而G1在大内存引用上则发挥其优势,平衡点在6-8GB之间
  • 参数设置

    • -XX:+UseG1GC,指定使用G1收集器
    • -XX:G1HeapRegionSize,设置每个Region的大小。默认的是2的幂值,范围是1MB至32MB之间,目标是根据最小的java堆大小划分出约2048个区域,默认是堆内存的1/2000
    • -XX:MaxGCPauseMillis,设置 期望达到的最大GC停顿时间指标,JVM会尽量实现,但不保证,默认200ms
    • -XX:ParallelGCThread,设置STW工作线程数的值,最多为8
    • -XX:ConcGCThreads,设置并发标记的线程数,将n设置为并行垃圾回收线程数(ParallelGCThread)的1/4左右
    • -XX:InitiatingHeapOccupancyPercent,设置触发并发GC周期的java堆占用阈值,超过此值就触发GC,默认45
  • 操作步骤

    • 开启G1回收器:-XX:+UseG1GC
    • 设置堆的最大内存:-Xmx
    • 设置最大停顿时间:-XX:MaxGCPauseMillis
    • G1中提供了三种垃圾回收模式:YoungGC、Mixed GC、Full GC,在不同情况下被触发
  • 使用场景

    • 面向服务端应用,针对具有大内存,多处理器的机器
    • 最主要的应用是需要低GC延迟,并具有大堆的应用程序提供解决方案
    • 在堆大小约6GB或更大时,可预测的暂停时间可以低于500ms
    • 用来替换掉JDK1.5中的CMS收集器,在下面的情况时,G1效果要好于CMS
      • 超过50%的java堆被活动数据占用
      • 对象分配频率或年代提升频率变化很大
      • GC停顿时间过长(大于0.5s)
    • 在Hotspot垃圾收集器里,除了G1以外,其他的垃圾收集器使用内置的jvm线程执行GC的多线程操作,而G1 GC可以采用线程承担后台运行的GC工作,即当jvm的GC线程处理速度慢时,系统会调用应用程序线程帮助加速垃圾回收过程
  • Region:化整为零

    • 使用G1收集器时,将整个堆内存划分为约2048个大小相同的独立Region,每个Region块大小根据堆空间的实际大小而定,值可以为1,2,4,8,16,32MB,所有的Region大小相同,且整个JVM周期不会变化
    • 虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离了。它们都是一部分Region的集合,通过Region的动态分配方式实现逻辑上的连续
  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • 垃圾回收过程

    • 年轻代GC

      • jvm启动时,G1先准备好Eden区,程序在运行过程中不断创建对象到Eden区,当Eden区空间耗尽时,G1会启动一次年轻代垃圾回收过程

      • 年轻代垃圾回收只会回收Eden和Survivor区

      • YGC时,首先G1停止应用程序的执行,G1创建回收集,回收集是指需要被回收的内存分段的集合,年轻代回收过程的回收集包含年轻代Eden和Survivor区的所有的内存分段

      • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

      • 然后开始回收过程

        • 第一阶段,扫描根:根是指static变量指向的对象,正在执行的方法调用链条上的局部变量等,根引用连同RSet记录的外部引用作为扫描存活对象的入口

        • 第二阶段,更新RSet:处理dirty card queue中的card,更新RSet,此阶段完成后,RSet可以准确反映老年代对所在内存分段中对象的引用

          dirty card queue:

          ​ 对于应用程序的引用赋值语句:object.field=object,jvm会在之前和之后执行特殊的操作以在dirty card queue中入队一个保存了对象引用 信息的card,在年轻代回收的时候,G1会对dirty card queue中所有的card进行处理,以更新RSet,保证RSet实时准确的反应引用关系

          ​ 为什么不在引用赋值语句处直接更新RSet呢?这是为了性能的需要,RSet的处理需要线程同步。开销会很大,使用队列性能会好很多

        • 第三阶段,处理RSet:识别被老年代对象指向的Eden中的对象,这些被指向的Eden中的对象被认为是存活的对象

        • 第四阶段,复制对象:此阶段,对象树被遍历,Eden区内存段中存活的对象会被复制到Survivor区中空的内存分段,Survivor区内存段中存活的对象如果年龄未达阈值,年龄会+1,达到阈值会被复制到old区中空的内存段,如果Survivor空间不够,Eden空间的部分数据会直接晋升到老年代空间

        • 第五阶段,处理引用:处理Soft、Weak、Phantom、Final、JNI Weak等引用,最终Eden空间的数据为空,GC停止工作,而目标内存中的对象都是连续的,没有碎片,所以复制过程可以达到内存整理的效果,减少碎片

    • 老年代并发标记过程(Concurrent Marking)

      • 初始标记阶段:标记从根节点直接可达的对象。这个阶段是STW的,并且会触发一次年轻代GC
      • 跟区域扫描:G1 GC扫描Survivor区直接可达的老年代区域对象,并标记被引用的对象,这一过程必须在YGC之前完成
      • 并发标记:在整个堆中进行并发标记,此过程可能被YGC中断,在并发标记阶段,若发现区域对象中的所有对象都是垃圾,那这个区域会立即回收,同时,并发标记过程中,会计算每个区域的对象活性(存活比例)
      • 再次标记:由于应用程序持续进行,需要修正上一次的标记结果,是STW的。G1中采用了比CMS更快的初始快照算法:SATB
      • 独占清理:计算各个区域的存活对象和GC回收比例,进行排序。识别可混合回收的区域,为下阶段做准备,STW,不会实际上去做垃圾收集
      • 并发清理阶段:识别并清理完全空闲的区域
    • 混合回收

      • 当愈来愈多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,该算法并不是一个old GC,除了回收整个Young Region还会回收一部分的old Region,可以选择那些old region进行收集 ,从而可以对垃圾回收的耗时时间进行控制,也要 注意的是Mixed GC 而不是Full GC

      • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

      • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

    • 如果需要,单线程、独占式、高强度的Full GC还是继续存在的,他针对GC的评估失败提供了一种失败保护机制,即强力回收

      • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析
  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • Remembered Set

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • 优化建议:

    JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

总结

  • 优先调整堆的大小让jvm自适应完成

  • 如果内存小于100M -》 Serial GC

  • 如果是单线程没有停顿时间的要求 -》 Serial GC

  • 想要最小化的使用内存和并行开销-》 Serial GC

  • 如果是多CPU,需要高吞吐量、运行停顿时间超过1s,-》Parallel GC 或jvm自行选择

  • 最大化应用程序的吞吐量 -》 Parallel GC

  • 如果是多CPU,追求低停顿时间,需快速响应,-》CMS、G1,官方推荐G1,性能高

  • 最小化GC的中断或停顿时间 -》 CMS

    JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

日志分析

  • 常用GC日志显示参数

    • -XX:+PrintGC:输出GC日志,-verbose:gc
    • -XX:+PrintGCDetails:输出GC详细日志
    • -XX:+PrintGCTimeStamps:输出GC的时间戳,以基准的形式
    • -XX:+PrintGCDateStamps:输出GC的时间戳,以日期的形式
    • -XX:+PrintHeapAtGC:在进行GC的前后大于出对的信息
    • -Xloggc:…/logs/gc.log:日志文件的输出路径
  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

-JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析

  • JVM-12-垃圾回收器介绍及简单垃圾回收日志分析