简介
说明
本文介绍Java的垃圾回收,包括:Young GC的触发时机,Full GC的触发时机,System.gc()作用。
Young GC(Minor GC)
什么时候会触发Minor GC?
- 大多数情况下,对象在年轻代中的Eden区进行分配,若Eden区没有足够空间,就会触发YGC(Minor GC)。
Full GC(Major GC)
简介
FGC处理的区域包括新生代和老年代。
什么时候会触发Full GC?
- 晋升到老年代的对象大于老年代的剩余空间。
- 老年代的内存使用率达到了一定阈值(默认是80%)。
- Metaspace(元空间)扩容到了-XX:MetaspaceSize 参数的指定值。(元空间在空间不足时会进行扩容)
- Minor GC时进行的检查
- 执行Minor GC的时候,JVM会检查老年代中最大连续可用空间是否大于了当前新生代所有对象的总大小。
- 如果大于,则直接执行Minor GC(这个时候执行是没有风险的)。
- 如果小于了,JVM会检查是否开启了空间分配担保机制
- 如果没有开启:直接执行Full GC。
- 如果开启:JVM会检查老年代中最大连续可用空间是否大于了历次晋升到老年代中的平均大小
- 如果小于:执行Full GC。
- 如果大于:执行Minor GC,如果Minor GC执行失败会执行Full GC
- 使用了大对象
- 大对象会直接进入老年代。比如:一次加载过多数据到内存(比如SQL查询未分页),导致大对象进入老年代。
- 相关参数:-XX:PretenureSizeThreshold。若对象大小大于此值,就会绕过新生代, 直接在老年代中分配。
- 程序执行了System.gc()
- 只是建议JVM执行FGC,并不一定会执行
- jmap 加了:live参数
- 例如:
- jmap -histo:live <pid>;
- jmap -dump:live,format=b,file=heap.bin <pid>
- 其他
- 上一次GC之后Heap的各域分配策略动态变化
- RMI等的定时触发
- YGC时的悲观策略
System.gc()
不要频繁使用gc函数。建议是:保持代码健壮(记得将不用的变量置为null),让虚拟机去管理内存。
System.gc():提醒虚拟机进行垃圾回收,回不回收由虚拟机决定。若虚拟机决定回收,也不是立刻进行回收,它是异步的。
当然,System.gc()也不是一点用也没有,当执行System.gc()之后,还是能一定程度影响垃圾回收的。如下所示:
package org.example.a;
class Person {
public Person(){
System.out.println("person created");
}
@Override
protected void finalize() throws Throwable {
System.out.println("gc ");
throw new Exception("no effect");
}
}
public class Demo {
public static void main(String[] args) {
Person per = new Person();
per = null;
System.gc();
System.out.println("hello world");
}
}
执行结果
person created
hello world
gc
若将System.gc()注释掉,执行结果
person created
hello world
其他网址
《Java开发实战经典》=> 第23章 Java内存模型=> 23.3 JVM垃圾收集
jvm gc 并行和并发的区别_百度知道