几种常见垃圾收集器理解

简单的讲述下几种垃圾回收器, 其中包含很多我的个人理解,难免有错漏之处, 欢迎指正

借用一张图
几种常见垃圾收集器理解

新生代的垃圾收集器

Serial 和ParNew

单线程和多线程的垃圾收集器, 可以配合CMS使用, 在回收的时候会暂停整个应用。

Parallel Scavenge

多线程的垃圾收集器, 他是控制吞吐量来减少停顿的垃圾收集器。 每次发生垃圾回收操作的时候, 如果把新生代的垃圾全部回收完这需要消耗太多的时间了, 那么我们设置一个吞吐量,当回收到一定量的时候就结束垃圾收集动作, 这样就相当于控制了垃圾收集的停顿时间了。

老年代垃圾收集器

Serial Old 和Parallel Old

这个就是新生代的Serial 和ParNew的老年代版本, 只是使用的是标记 - 整理 算法来回收垃圾了。

老年代中存放的对象都是默认为会长期存活的对象, 并且一般老年代的空间大, 如果使用复制回收算法, 可能会有效率不高, 或者空间浪费太多的问题。

CMS垃圾回收器

这个是老年代独有的垃圾回收器, 它的目的是为了尽可能的减少停顿时间。
几种常见垃圾收集器理解
可以从图中看到只有在初始标记和并发标记的时候才会停顿, 而这两个过程在垃圾收集的动作中占用的时间并不多, 真正占大头的是垃圾清理和全量标记的操作。 它刚好把这两个耗时较长的操作使用并发执行替代了。 重新标记是为了修复在并发标记的过程中新产生的垃圾, 也不会占用多少时间的。

CMS通过并行操作能够最大限度的减少了应用的停顿时间,但是它也是有代价的。

缺点:

  1. 并行标记和并行清理 会占用CPU资源, 也就是会和应用竞争CPU资源, 但是现在多核时代了, 忽略它
  2. 因为并行清理, 可能会在并行清理的过程中有新的垃圾产生, 但是这些垃圾只能等到下次清理,

如果并行清理的速度赶不上垃圾产生的速度, 最后就会导致jvm启动备用方案, 使用Parallel Old 垃圾收集器来收集老年代垃圾

  1. 由于采用的是 标记- 清除(不是标记 - 整理)的收集算法,这会在老年代中产生大量的碎片空间。 这些碎片空间会影响大对象的内存分配。 会出现可用内存很多,但是都是碎片从而导致不够用。 当CMS顶不住了时候,jvm 又会弃用备用方案, 使用Parallel Old 垃圾收集器来收集老年代垃圾。

G1 垃圾收集器

横跨新生代和老年代垃圾收集器。 回收的性能很高
几种常见垃圾收集器理解

  • 它可以并行并发的进行垃圾收集。 并行并发的过程和CMS很像。
  • 他把内存分成了很多个小区间Region。
  • 它也有分代的概念, 但是它是把一个个Region作为老年代或者新生代的。 并且新生代和老年代可能是不连续的Region
  • 它从整体来看是标记 - 整理 的垃圾回收算法,但是在每个Region内部又是使用复制清除算法
  • 它维护了每个Region的回收价值的列表, 可是根据需要对价值最高的一些Region 进行垃圾回收。
  • 如果一个Region中垃圾占比过高, 他会把这个Region整个回收,会把存活对象转移到另外的Region中, 保持Region的紧凑。
  • 当一个Region装不下一个大对象的时候会把临近的Region也用上来一起装大对象。

当G1收集器hold不住的时候, jvm会FullGC 暂停整个应用来进行垃圾回收。

ZGC 垃圾收集器

Java 11包含一个全新的垃圾收集器–ZGC,它由Oracle开发,承诺在数TB的堆上具有非常低的暂停时间。

参考这篇博客吧 https://www.cnblogs.com/huanchupkblog/p/10947919.html

我也不理解器原理, 后面会单开博客说明的。