Full GC是一种垃圾回收机制,用于回收整个堆内存中的所有的未使用的对象,包括年轻代、老年代和永久代(元空间)中的对象。
Full GC会暂停除了GC线程外的所有的线程,这种暂停时间相对较长,对系统性能影响较大
触发Full GC的条件
1.显式调用system.gc(),此方法只是建议系统执行Full GC,提高Full GC执行的概率,但不是必定会执行。
2.老年代空间不足。
对象进入老年代的条件:
- 对象年龄超过15岁(默认)【-XX:MaxTenuringThreshold】
- 动态年龄判断:Survivor区的对象年龄从小到大进行累加,当累加到X年龄(某个年龄)时占用空间的总和大于50%(可以使用-XX:TargetSurvivorRatio=?来设置保留多少空闲空间,默认值是50),那么比X年龄大的对象都会晋升到老年代
- 大对象直接进入老年代(Serial和ParNew收集器)(默认1M)【-XX:PretenureSizeThreshold】
- 空间担保机制
3.Eden区满了,触发Minor GC后,存活的对象无法全部晋升到Survivor区,会由老年代担保机制将剩余的对象直接放入老年代,如果老年代也放不下,就会触发Full GC
4.元空间内存不足。
5.CMS垃圾处理器在并发标记阶段出现“Concurrent Mode Failure”时,会触发一次Full GC。
如何避免Full GC
1.调整堆内存大小: 如果堆内存设置得太小,容易导致频繁的垃圾回收,特别是Full GC。增大堆内存可以减少垃圾回收的频率。可以通过 -Xms 和 -Xmx 参数分别设置初始堆大小和最大堆大小。
java -Xms512m -Xmx1024m -jar YourApplication.jar
2.合理设置新生代和老年代的比例: 年轻代存活对象晋升到老年代时会触发Full GC,合理设置新生代和老年代的比例可以影响对象晋升的速度。可以通过 -XX:NewRatio 参数来调整新生代和老年代的比例。
java -XX:NewRatio=2 -jar YourApplication.jar
3.选择合适的垃圾回收器: 根据应用程序的特性选择合适的垃圾回收器。不同的垃圾回收器有不同的特点,比如CMS(Concurrent Mark-Sweep)和G1(Garbage-First)是以减小停顿时间为目标的回收器,适用于对响应时间敏感的应用。
java -XX:+UseConcMarkSweepGC -jar YourApplication.jar
4.调整新生代的大小: 通过调整新生代的大小,可以影响对象在年轻代的存活时间,从而影响晋升到老年代的速度。可以使用参数 -Xmn 来设置新生代的大小。
java -Xmn256m -jar YourApplication.jar
5.避免过度使用Finalizer: 使用 finalize 方法可能导致对象在垃圾回收时的额外开销。尽量避免过度依赖 finalize 方法。
6.检查内存泄漏: 内存泄漏可能导致堆内存的不断增加,最终导致Full GC。使用内存分析工具(如VisualVM、MAT等)来检查和解决潜在的内存泄漏问题。
7.监控和调优: 定期监控应用程序的垃圾回收情况,通过日志或监控工具(如VisualVM、JConsole等)来分析GC日志,找到GC发生的原因,并根据实际情况进行调优。