面试:JVM 垃圾回收器

作者: Tim在路上 | 来源:发表于2020-05-27 22:38 被阅读0次

我们都知道java的默认垃圾回收器是jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代),但是一般我们都不会使用,但是在
jdk1.9 默认垃圾收集器G1

我们可以采用以下命令来查看垃圾收集器:

java -XX:+PrintCommandLineFlagsjvm version
-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型
-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断
-XX:InitialHeapSize=266287936 -XX:MaxHeapSize=4260606976 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+U
seParallelGC

1. 设置垃圾回收器参数以及意义

-XX:+UseSerialGC,虚拟机运行在Client模式下的默认值,Serial+Serial Old。

-XX:+UseParNewGC,ParNew+Serial Old,在JDK1.8被废弃,在JDK1.7还可以使用。

-XX:+UseConcMarkSweepGC,ParNew+CMS+Serial Old。

-XX:+UseParallelGC,虚拟机运行在Server模式下的默认值,Parallel Scavenge+Serial Old(PS Mark Sweep)。

-XX:+UseParallelOldGC,Parallel Scavenge+Parallel Old。

-XX:+UseG1GC,G1+G1。

设置步骤:
  1. 默认参数:-XX:+PrintGCDetails -XX:+PrintCommandLineFlags 用于打印具体的信息
  2. 添加上面的参数

// 修改后的输出参数

-XX:InitialHeapSize=266287936 -XX:MaxHeapSize=4260606976 -XX:MaxNewSize=697933824 -XX:MaxTenuringThreshold=6 -XX:OldPLABSize=16 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC 

2. 垃圾回收概念

image.png
基本概念

并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。

并发(Concurrent):指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行),用户程序在继续运行。而垃圾收集程序运行在另一个CPU上。

吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)。

假设虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。

Minor GC 和 Full GC

新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快。具体原理见上一篇文章。

老年代GC(Major GC / Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。

3. 垃圾回收器

新生代:

1. Serial

新生代串行的垃圾收集器,采用复制算法,垃圾回收时必须暂停全部的工作线程,是一种独占式的垃圾回收器。

优点:简单高效,常做client模式桌面应用;
缺点:串行,无法利用多核优势

2. PerNew

新生代多线程垃圾回收器,是独占的,比起Serial多了多线程,场合CMS搭配使用;

优点:适用多核

3. Parallel Scavenge 收集器

Parallel Scavenge收集器也是一个并行的多线程新生代收集器,它也使用复制算法。

但是不同的是Parallel Scavenge 关注的是吞吐量,也就是整体的停顿时间占的比例,不关心,用户停顿的时长;

其他的都是关注用户停顿时间,适合需要与用户交互的程序。

高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

Parallel Scavenge收集器无法与CMS收集器配合使用,一般Serial Old,Parallel Old

所以,java默认的垃圾回收器适合纯服务器开发;

老年代:

Serial Old收集器

Serial Old 是 Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”(Mark-Compact)算法。

Parallel Old收集器

使用多线程和“标记-整理”算法。所以在Parallel Old诞生以后,“吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,

CMS

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它非常符合那些集中在互联网站或者B/S系统的服务端上的Java应用,这些应用都非常重视服务的响应速度。从名字上(“Mark Sweep”)就可以看出它是基于“标记-清除”算法实现的。

CMS收集器工作的整个流程分为以下4个步骤:

  • 初始标记(CMS initial mark):仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要“Stop The World”。
  • 并发标记(CMS concurrent mark):进行GC Roots Tracing的过程,在整个过程中耗时最长。
  • 重新标记(CMS
    remark):为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。此阶段也需要“Stop The World”。
  • 并发清除(CMS concurrent sweep)

优点: CMS是一款优秀的收集器,它的主要优点在名字上已经体现出来了:并发收集、低停顿,因此CMS收集器也被称为并发低停顿收集器(Concurrent Low Pause Collector)。使用于 B/S架构,与用户交流;

缺点:1.对CPU资源非常敏感 其实,面向并发设计的程序都对CPU资源比较敏感。在并发阶段,它虽然不会导致用户线程停顿,但会因为占用了一部分线程(或者说CPU资源)而导致应用程序变慢,总吞吐量会降低。CMS默认启动的回收线程数是(CPU数量+3)/4;2.标记-清除算法导致的空间碎片 3.回收失败会退回到Serial Old;

G1收集器

G1(Garbage-First)收集器,它是一款面向服务端应用的垃圾收集器;

1.并行与并发 G1 能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短“Stop The World”停顿时间;

2.分代收集 与其他收集器一样,分代概念在G1中依然得以保留。

3.空间整合 G1从整体来看是基于“标记-整理”算法实现的收集器;

4.可预测的停顿 这是G1相对CMS的一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了降低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,

G1收集器之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(这也就是Garbage-First名称的来由)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。

G1的适用场景:1.多核CPU,JVM内存占用较大的应用(纸上4G)2.运行过程产生大量碎片需要压缩,3.更可控的GC停顿周期,防止高并发下的雪崩;

4. 总结

image.png

相关文章

网友评论

    本文标题:面试:JVM 垃圾回收器

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