0%

Java 虚拟机 6 :垃圾回收机制

一、概述

垃圾收集 Garbage Collection 通常被称为“GC”。 jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的.

二、GC 算法与垃圾收集器总结

垃圾回收机制总结

下图是 HotSpot 虚拟机的垃圾收集器(图片来源于 https://blogs.oracle.com/jonthecollector/our-collectors

查看JDK使用的是什么垃圾收集器,可使用命令:

1
2
java -XX:+PrintCommandLineFlags -version
java -XX:+PrintGCDetails -version

运行结果示例:

GC 算法 垃圾收集器-纯洁的微笑

三、垃圾回收的时机与过程

不同的垃圾回收器的回收过程其实是有些差别的,下面分别以以 CMS垃圾回收器 以及 G1 垃圾回收器为例。

CMS收集器的GC过程


G1收集器的GC过程

G1把内存分成一块块的Region,每块的Region的大小都是一样的。G1 保留了 YoungGC 并加上了一种全新的Mixed GC用于收集老年代。G1中没有Full GC,G1中的Full GC是通过调用serialOldGC进行全堆扫描实现的(包括eden、survivor、old、perm)。

1.YoungGC年轻代收集
在分配一般对象(非巨型对象)时,当所有eden region使用达到最大阀值并且无法申请足够内存时,会触发一次YoungGC。每次younggc会回收所有Eden以及Survivor区,并且将存活对象复制到Old区以及另一部分的Survivor区。

2.Mixed GC
当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。

3.有两种情况会出现 G1 Full GC
G1的初衷就是要避免Full GC的出现。但如果出现以下两种情况,G1会停止应用程序的执行(Stop-The-World),退化成使用单线程的内存回收算法(调用serialOldGC)进行垃圾回收, 性能会非常差,应用程序停顿时间会很长。

  • 拷贝存活对象晋升失败,无法找到可用的空闲分区,GC日志记录为to-space exhausted。或者分配巨型对象无法在老年代找到连续足够的分区

  • 当发生第一个条件后,G1会尝试增加堆使用量,如果扩展失败,那么会触发安全措施机制同时发生 调用serialOldGC 进行 Full GC

深入剖析JVM:G1收集器+回收流程+推荐用例

HotSpot VM 的 GC分类

周志明先生在《深入理解 Java 虚拟机》第二版中 P92 如是写道:

“老年代 GC(Major GC/Full GC),指发生在老年代的 GC……”

上面的说法已经在《深入理解 Java 虚拟机》第三版中被改正过来了。感谢 R 大的回答:

总结:
针对 HotSpot VM 的实现,它里面的 GC 其实准确分类只有两大种:

部分收集 (Partial GC):

  • 新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集;
  • 老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC 在有的语境中也用于指代整堆收集;
  • 混合收集(Mixed GC):对整个新生代和部分老年代进行垃圾收集。
  • 整堆收集 (Full GC):收集整个 Java 堆和方法区。

整堆收集 (Full GC):收集整个 Java 堆和方法区。

四、GC日志分析

Java GC 分析

五、Java 服务 GC 参数调优案例

Java 服务 GC 参数调优案例

六、参考资料

Our Collectors
GC 的分分类
JVM垃圾回收
深入剖析JVM:G1收集器+回收流程+推荐用例
GC 算法 垃圾收集器-纯洁的微笑