什么时候会触发FullGC?

1 个回答

  • 玄差
    没觉得一年比一年自由,但确实一年比一年通透。
    ### 触发 Full GC 的情况 除了直接调用 `System.gc` 外,触发 Full GC 执行的情况有如下四种: 1. **旧生代空间不足** - **原因**:旧生代空间不足通常在新生代对象转入旧生代或创建大对象、大数组时出现。 - **后果**:执行 Full GC 后空间仍然不足,则会抛出 `java.lang.OutOfMemoryError: Java heap space`。 - **调优建议**:尽量在 Minor GC 阶段回收对象,让对象在新生代多存活一段时间,避免创建过大的对象和数组。 2. **永久代(PermGen)空间满** - **原因**:PermGen 中存放的是类的信息等。当系统中加载的类、反射类和调用的方法较多时,PermGen 可能会被占满。 - **后果**:如果 Full GC 仍然不能回收空间,JVM 会抛出 `java.lang.OutOfMemoryError: PermGen space`。 - **调优建议**:增大 PermGen 空间或使用 CMS GC。 3. **CMS GC 时出现 promotion failed 和 concurrent mode failure** - **promotion failed**:在进行 Minor GC 时,Survivor Space 放不下对象,导致对象进入旧生代,而此时旧生代也放不下。 - **concurrent mode failure**:在执行 CMS GC 的过程中,同时有对象要放入旧生代,而此时旧生代空间不足。 - **调优建议**:增大 Survivor Space 和旧生代空间,或调低触发并发 GC 的比率。在 JDK 5.0+ 和 6.0+ 版本中,由于 JDK 的 bug 可能导致 CMS 在 remark 完毕后很久才触发 sweeping 动作,可通过设置 `-XX:CMSMaxAbortablePrecleanTime=5`(单位为 ms)来避免。 4. **统计得到的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩余空间** - **原因**:为了避免新生代对象晋升到旧生代导致旧生代空间不足,Hotspot 在进行 Minor GC 时会做一个判断。如果之前统计的 Minor GC 晋升到旧生代的平均大小大于旧生代的剩余空间,则直接触发 Full GC。 - **例子**:如果程序第一次触发 Minor GC 后,有 6MB 的对象晋升到旧生代,那么下一次 Minor GC 发生时,首先检查旧生代的剩余空间是否大于 6MB,如果小于 6MB,则执行 Full GC。 - **PS GC**:新生代采用 PSGC 时,方式稍有不同,PS GC 在 Minor GC 后也会检查旧生代的剩余空间是否足够,如不足则触发对旧生代的回收。 #### 其他情况 - **RMI 导致的 Full GC**:对于使用 RMI 进行 RPC 或管理的 Sun JDK 应用,默认情况下会每小时执行一次 Full GC。可以通过启动时设置 `-Dsun.rmi.dgc.client.gcInterval=3600000` 来调整 Full GC 执行的间隔时间,或通过 `-XX:+DisableExplicitGC` 来禁止 RMI 调用 `System.gc`。 通过理解和调优上述触发 Full GC 的情况,可以有效地优化 JVM 的性能,避免不必要的 Full GC 触发。
    发布于 2024-07-03 09:47 •IP属地 山西
    举报
    评论
    收藏