JVM垃圾收集

发布时间 2023-07-15 15:21:33作者: 王景迁

默认垃圾收集器

JDK1.7和JDK1.8默认垃圾收集器都是ParallelScavenge(新生代)+ParallelOld(老年代)
JDK1.9默认垃圾收集器G1

查看命令:java -XX:+PrintCommandLineFlags -version

G1

JDK 1.7推出的垃圾收集器,特点如下:

1 使用多核CPU来缩短Stop-The-World停顿的时间
2 分代收集
3 基于标记-整理算法实现,不产生空间碎片
4 建立了可预测的停顿时间模型:能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。G1把整个Java堆划分为多个大小相等的独立区域(Region),新生代和老年代不再物理隔离,都是一部分Region的集合。G1之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集。

触发GC

GC有两种类型:Minor GC和Full GC。
Minor GC:当生成新对象,并且在Eden区申请空间失败时,会触发Minor GC,把存活对象复制到From Survivor区或者To Survivor区。因为Java对象大多具备朝生夕灭的特性,所以Minor GC会频繁进行。
Full GC:对整个堆进行整理,伴随至少一次的Minor GC,比Minor GC慢10倍以上。
可能导致Full GC的原因
1 老年代(Tenured)被填满
2 System.gc( )被显示调用

内存分配与回收策略

对象优先在Eden区中分配

一般对象在新生代Eden区中分配。当Eden区没有足够空间分配时,JVM发起一次Minor GC。把存活对象复制到From Surivor区。

Eden区清理后可以存放新的对象。当Eden区再次被用完,触发MinorGC,将Eden区与From Surivor区存活对象复制到To Surivor区。

下次MinorGC时,将Eden区与To Surivor区中存活对象复制到From Surivor区。

大对象直接进入老年代

大对象指需要大量连续内存空间的Java对象,例如很长的字符串和大数组。

长期存活的对象将进入老年代

JVM给每个对象定义了一个对象年龄(Age)计数器。如果对象在Eden区分配并经过第一次MinorGC后仍然存活,且能被Survivor区容纳,则将该对象移动到Survivor区,对象年龄设为1。该对象在Survivor区每熬过一次MinorGC,年龄增加1岁,当年龄增加到一定程度(默认为15岁),晋升到老年代。