JVM-【面试题】-垃圾收集算法+垃圾收集器,以后就不用担心对象那些事了

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、垃圾收集算法

在jvm里对可回收的对象在不同的垃圾收集器里有不同的回收算法具体的可以分为这四种分代收集算法、复制算法、标记清除算法、标记整理算法

1.1 分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法这种算法没有什么新的思想只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

比如在新生代中每次收集都会有大量对象(近99%)死去所以可以选择复制算法只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的而且没有额外的空间对它进行分配担保所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。

注意“标记-清除”或“标记-整理”算法会比复制算法慢10倍以上。

1.2 标记-复制算法

为了解决效率问题“复制”收集算法出现了。它将内存分成大小相同的两块每次只使用其中一块。当这块的内存使用完后就将存活的对象复制到另外一块去然后再把使用的空间一次清理掉。这样就使得每一次的内存回收都是对内存区间的一半进行回收。

这种算法是使用在新生代因为新生代的对象都是朝生夕死非常适合使用复制算法。

1.3 标记-清除算法

算法分为“标记”和“清除”阶段标记存活的对象 统一回收所有未被标记的对象(一般选择这种)也可以反过来标记出所有需要回收的对象在标记完成后统一回收所有被标记的对象 。它是最基础的收集算法比较简单但是会带来两个明显的问题

  1. 效率问题 (如果需要标记的对象太多效率不高)

  1. 空间问题标记清除后会产生大量不连续的碎片

1.4 标记-整理算法

根据老年代的特点特出的一种标记算法标记过程仍然与“标记-清除”算法一样但后续步骤不是直接对可回收对象回收而是让所有存活的对象向一端移动然后直接清理掉端边界以外的内存。

二、垃圾收集器

本次只介绍jdk1.8常用到的垃圾收集器

如果说收集算法是内存回收的方法论那么垃圾收集器就是内存回收的具体实现。

虽然我们对各个收集器进行比较但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现更加没有万能的垃圾收集器我们能做的就是根据具体应用场景选择适合自己的垃圾收集器。试想一下如果有一种四海之内、任何场景下都适用的完美收集器存在那么我们的Java虚拟机就不会实现那么多不同的垃圾收集器了。

2.1 Serial收集器

参数-XX:+UseSerialGC年轻代 -XX:+UseSerialOldGC老年代

Serial串行收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 “单线程” 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程 "Stop The World" 直到它收集结束。

新生代采用复制算法老年代采用标记-整理算法

虚拟机的设计者们当然知道Stop The World带来的不良用户体验所以在后续的垃圾收集器设计中停顿时间在不断缩短仍然还有停顿寻找最优秀的垃圾收集器的过程仍然在继续。

但是Serial收集器有没有优于其他垃圾收集器的地方呢当然有它简单而高效与其他收集器的单线程相比。Serial收集器由于没有线程交互的开销自然可以获得很高的单线程收集效率。

Serial Old收集器是Serial收集器的老年代版本它同样是一个单线程收集器。它主要有两大用途一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用另一种用途是作为CMS收集器的后备方案

2.2 Parallel Scavenge收集器jdk1.8默认垃圾收集器

参数-XX:+UseParallelGC(年轻代)、-XX:+UseParallelOldGC(老年代)

Parallel收集器其实就是Serial收集器的多线程版本除了使用多线程进行垃圾收集外其余行为控制参数、收集算法、回收策略等等和Serial收集器类似。默认的收集线程数跟cpu核数相同当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数但是一般不推荐修改。

Parallel Scavenge收集器关注点是吞吐量高效率的利用CPU。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间提高用户体验。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。 Parallel Scavenge收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量如果对于收集器运作不太了解的话可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。

新生代采用复制算法老年代采用标记-整理算法。

Parallel Old收集器是Parallel Scavenge收集器的老年代版本。使用多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器)。

2.3 ParNew收集器

参数-XX:+UseParNewGC(年轻代)

ParNew收集器其实跟Parallel收集器很类似区别主要在于它可以和CMS收集器配合使用。

新生代采用复制算法老年代可以配合其他垃圾收集器

它是许多运行在Server模式下的虚拟机的首要选择除了Serial收集器外只有它能与CMS收集器配合工作

1.4 CMS收集器

参数-XX:+UseConcMarkSweepGC(老年代)

CMSConcurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用它是HotSpot虚拟机第一款真正意义上的并发收集器它第一次实现了让垃圾收集线程与用户线程基本上同时工作。

从CMS收集器是一种“标记-清除”算法实现的它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤

初始标记 暂停所有的其他线程(STW)并记录下gc roots直接能引用的对象速度很快。

并发标记 并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程 这个过程耗时较长但是不需要停顿用户线程 可以与垃圾收集线程一起并发运行。因为用户程序继续运行可能会有导致已经标记过的对象状态发生改变。

重新标记 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录(主要是处理漏标问题)这个阶段的停顿时间一般会比初始标记阶段的时间稍长远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法(见下面详解)做重新标记。

并发清理 开启用户线程同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理(见下面三色标记算法详解)。

并发重置重置本次GC过程中的标记数据。

从它的名字就可以看出它是一款优秀的垃圾收集器主要优点并发收集、低停顿。但是它有下面几个明显的缺点

  • 对CPU资源敏感会和服务抢资源

  • 无法处理浮动垃圾(在并发标记和并发清理阶段又产生垃圾这种浮动垃圾只能等到下一次gc再清理了)

  • 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生当然通过参数-XX:+UseCMSCompactAtFullCollection可以让jvm在执行完标记清除后再做整理

  • 执行过程中的不确定性会存在上一次垃圾回收还没执行完然后垃圾回收又被触发的情况特别是在并发标记和并发清理阶段会出现一边回收系统一边运行也许没回收完就再次触发full gc也就是"concurrent mode failure"此时会进入stop the world用serial old垃圾收集器来回收

CMS的相关核心参数

  1. -XX:+UseConcMarkSweepGC启用cms

  1. -XX:ConcGCThreads并发的GC线程数

  1. -XX:+UseCMSCompactAtFullCollectionFullGC之后做压缩整理减少碎片

  1. -XX:CMSFullGCsBeforeCompaction多少次FullGC之后压缩一次默认是0代表每次FullGC后都会压缩一次

  1. -XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC默认是92这是百分比

  1. -XX:+UseCMSInitiatingOccupancyOnly只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值)如果不指定JVM仅在第一次使用设定值后续则会自动调整

  1. -XX:+CMSScavengeBeforeRemark在CMS GC前启动一次minor gc降低CMS GC标记阶段(也会对年轻代一起做标记如果在minor gc就干掉了很多对垃圾对象标记阶段就会减少一些标记时间)时的开销一般CMS的GC耗时 80%都在标记阶段

  1. -XX:+CMSParallellnitialMarkEnabled表示在初始标记的时候多线程执行缩短STW

  1. -XX:+CMSParallelRemarkEnabled在重新标记的时候多线程执行缩短STW;

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6