一、概述
垃圾收集 Garbage Collection 通常被称为“GC”。 jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的.
二、GC 算法与垃圾收集器总结
下图是 HotSpot 虚拟机的垃圾收集器(图片来源于 https://blogs.oracle.com/jonthecollector/our-collectors)
查看JDK使用的是什么垃圾收集器,可使用命令:
1 | java -XX:+PrintCommandLineFlags -version |
运行结果示例:
三、垃圾回收的时机与过程
不同的垃圾回收器的回收过程其实是有些差别的,下面分别以以 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
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 参数调优案例
六、参考资料
Our Collectors
GC 的分分类
JVM垃圾回收
深入剖析JVM:G1收集器+回收流程+推荐用例
GC 算法 垃圾收集器-纯洁的微笑