什么情况下会触发 Java 的 Full GC?

Full GC(完全垃圾回收)是 Java 中的一个重要垃圾回收阶段,它会回收 整个堆内存,包括 新生代老年代。触发 Full GC 的条件通常比 Young GC 更为复杂且影响较大,因为它会导致 JVM 停顿时间较长。下面是一些常见的触发 Full GC 的情况:


1. 老年代内存不足

  • 老年代 的内存空间不足时,JVM 会触发 Full GC
  • 在垃圾回收过程中,如果 新生代 的回收没有释放足够的内存空间供老年代使用,或者 老年代 的对象数量增多导致空间耗尽时,会触发 Full GC

例子:

  • Minor GC 后,如果新生代的对象经过若干次晋升后占用了大量的老年代空间,老年代内存不足时,会触发 Full GC

2. 长时间没有进行过 Full GC

  • 如果 JVM 在长时间内没有执行过 Full GC,并且 新生代老年代 的内存空间都已经满了,JVM 会自动触发 Full GC 来释放内存。

例子:

  • 如果一个应用程序长期运行并且 Minor GC 无法回收足够的内存来供老年代使用,可能会触发 Full GC

3. 调用 System.gc()

  • 如果显式调用了 System.gc() 方法,JVM 会尝试执行 Full GC
  • 这个方法虽然建议避免使用,因为它会增加不必要的性能开销,但仍然会强制进行 Full GC

例子:

System.gc();  // 强制调用 Full GC

4. 内存溢出(OutOfMemoryError)

  • 当 JVM 遇到内存溢出的情况时,可能会触发 Full GC。例如,当老年代空间不足以存放对象时,Full GC 会被触发。但如果内存依然不足,最终会抛出 OutOfMemoryError

例子:

  • 当老年代的空间无法为新对象分配内存时,JVM 会尝试进行 Full GC,但如果回收后仍然无法满足要求,就会抛出内存溢出异常。

5. JVM 参数的调整

  • 某些 JVM 参数的调整可能会导致 Full GC 的触发。例如:

    • -XX:MinHeapFreeRatio-XX:MaxHeapFreeRatio:控制堆内存空闲比例,可能会触发 Full GC
    • -XX:SurvivorRatio:调整 Survivor 区Eden 区 的比例,如果调整后内存压力较大,可能会触发 Full GC

例子:

  • 修改 -Xmx-Xms 参数时,JVM 可能会执行 Full GC 来调整堆内存大小。

6. 堆内存的配置发生变化

  • 修改堆内存配置,如 最大堆内存大小初始堆内存大小,可能会导致堆内存的重新分配,从而触发 Full GC

例子:

  • 修改启动参数 -Xmx-Xms 时,JVM 会重新分配堆内存,可能会触发 Full GC

7. 垃圾回收器的切换

  • 在一些情况下,当 JVM 切换垃圾回收器时,例如从 Parallel GC 切换到 G1 GC,也可能触发一次 Full GC 来适应新的垃圾回收策略。

例子:

  • 启用 -XX:+UseG1GC 配置时,JVM 可能会执行一次 Full GC 来完成策略调整。

8. 类加载过程

  • 在类加载过程中,尤其是当加载大量类时,如果内存不足,JVM 会触发 Full GC 来释放空间。特别是在 Metaspace(JDK 8 及以后)或 PermGen(JDK 7 及以前)空间不足时,可能会发生 Full GC

例子:

  • 动态加载大量类时,可能会导致 Metaspace 空间不足,从而触发 Full GC

总结

触发条件 描述
老年代内存不足 当老年代空间不足时,触发 Full GC
长时间未执行 Full GC 如果长时间没有进行过 Full GC,内存压力增大时会触发。
调用 System.gc() 显式调用 System.gc() 方法会触发 Full GC
内存溢出(OutOfMemoryError) 当内存溢出发生时,Full GC 会被触发来尝试回收内存。
JVM 参数调整 修改堆内存大小或其他内存参数时,JVM 可能会触发 Full GC
堆内存配置变化 堆内存的配置发生变化时,JVM 可能会执行一次 Full GC
垃圾回收器切换 在垃圾回收器切换时,可能会触发 Full GC
类加载过程 在加载类时,如果内存不足,也可能触发 Full GC

结论:

Full GC 是在堆内存出现压力时,特别是老年代空间不足时触发的,它会回收整个堆内存,包括新生代和老年代。由于 Full GC 会导致较长时间的停顿,因此在应用中需要尽量避免频繁触发。

什么情况下会触发 Java 的 Full GC?的更多相关文章

  1. Java面试题之什么情况下会触发类的初始化

    以下情况会触发类的初始化: 遇到new,getstatic,putstatic,invokestatic这4条指令: 使用java.lang.reflect包的方法对类进行反射调用: 初始化一个类的时 ...

  2. 什么情况下不能使用 Java 泛型

    1. 前言 Java 1.5 引入了泛型来保证类型安全,防止在运行时发生类型转换异常,让类型参数化,提高了代码的可读性和重用率.但是有些情况下泛型也是不允许使用的,今天就总结一下编码中不能使用泛型的一 ...

  3. 触发JVM进行Full GC的情况及应对策略

    堆内存划分为 Eden.Survivor 和 Tenured/Old 空间,如下图所示: 从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为M ...

  4. @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码

    一.前言 这篇算是类加载器的实战第五篇,前面几篇在这里,后续会持续写这方面的一些东西. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 ...

  5. Java之HashMap在多线程情况下导致死循环的问题

    PS:不得不说Java编程思想这本书是真心强大.. 学习内容: 1.HashMap<K,V>在多线程的情况下出现的死循环现象   当初学Java的时候只是知道HashMap<K,V& ...

  6. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

  7. Java基础知识强化之IO流笔记06:有return的情况下try catch finally的执行顺序

    1. 给出结论: (1)不管有木有出现异常,finally块中代码都会执行:(2)当try和catch中有return时,finally仍然会执行:(3)finally是在return后面的表达式运算 ...

  8. Java高并发情况下的锁机制优化

    本文主要讲并行优化的几种方式, 其结构如下: 锁优化 减少锁的持有时间 例如避免给整个方法加锁 1 public synchronized void syncMethod(){ 2 othercode ...

  9. layoutSubviews 在什么情况下会被触发

    layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubviews 2.addSubview会触发layoutSubviews 3.设置view的Frame会触 ...

  10. 【Java面试题】25 同步和异步有何异同,在什么情况下分别使用他们?举例说明。

    如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取. 当应用程序在对象上调用了一个需要花费很长时间 ...

随机推荐

  1. Alink漫谈(二十一) :回归评估之源码分析

    Alink漫谈(二十一) :回归评估之源码分析 0x00 摘要 Alink 是阿里巴巴基于实时计算引擎 Flink 研发的新一代机器学习算法平台,是业界首个同时支持批式算法.流式算法的机器学习平台.本 ...

  2. 2.vue3修改端口号

    根目录新建vue.vonfig.js module.exports = { devServer: { port: 8081, // 端口 }, lintOnSave: false // 取消 esli ...

  3. C# 程序流控制 条件语句

    C#语言最基本的重要语句:控制程序流的语句.它们不是按代码在程序中的排列位置顺序执行的. 条件语句 条件语句可以根据条件是否满足或根据表达式的值来控制代码的执行分支.C#有两个控制代码的分支结构: i ...

  4. win10安装MongoDB 5.0

    1.首先去官网下载安装包:https://www.mongodb.com/try?tck=docs_navbar 2.安装过程一路下一步就行,选择complete安装,可以勾选安装Compass工具 ...

  5. python渗透脚本小子速成教程

    python代码即脚本,脚本小子即是python.python只有几个类:常量.字符串,API不可知的数,变量定义.常量是不变固定的,变量是可变的,字符串一般都是单引号''和双引号"&quo ...

  6. 常用的linux命令以及详解

    Linux系统中包含了大量的命令,这些命令是用户与系统交互的主要方式.以下是一些常用的Linux命令及其详细解释: 1. 文件和目录操作 ls:列出目录内容. ls:列出当前目录的文件和子目录. ls ...

  7. Docker 容器的数据卷 以及 数据卷容器

    Docker 容器删除后,在容器中产生的数据还在吗? 答案是 不在 Docker 容器和外部机器可以直接交换文件吗? 在没有数据卷的情况下,答案是 不可以 如下图:外部机器:Windows系统(自己的 ...

  8. SparkRDD算子(transformations算子和actions算子)

    RDD提供了两种类型的操作:transformation和action1.所有的transformation都是采用的懒策略,如果只是将transformation提交是不会执行计算的,计算只有在ac ...

  9. 使用mybatis-plus转换枚举值

    1. 使用mybatis-plus转换枚举值 枚举值转换方式有很多,有以下方式: 后端写一个通用方法,只要前端传枚举类型,后端返回相应的枚举值前端去匹配 优点:能够实时保持数据一致性 缺点:如果有大量 ...

  10. 基于Microsoft.Extensions.VectorData实现语义搜索

    大家好,我是Edison. 上周水了一篇 Microsoft.Extensions.AI 的介绍文章,很多读者反馈想要了解更多.很多时候,除了集成LLM实现聊天对话,还会有很多语义搜索和RAG的使用场 ...