完整的GC过程

原文地址: https://www.cnblogs.com/shuiyj/p/12640692.html

在这里插入图片描述
GC流程是每一个Java开发人员都应该掌握的内容。你知道什么时候触发Minor GC?什么时候触发
Minor GC 的过程是怎么样的?Full GC 的过程又是怎么样的?这一切都要从「压死骆驼的最后一根稻草」说起。

看图,看图,看图。跟着我画的流程图走一遍,就清楚了!

挤满新生代的最后一个对象
我们应当知道,新创建的对象一般会被分配在新生代中。常用的新生代的垃圾回收器是 ParNew 垃圾回收器,它按照 8:1:1 将新生代分成 Eden 区,以及两个 Survivor 区。

某一时刻,我们创建的对象将 Eden 区全部挤满,这个对象就是「挤满新生代的最后一个对象」。此时,Minor GC 就触发了。

正式 Minor GC 前的检查
在正式 Minor GC 前,JVM 会先检查新生代中对象,是比老年代中剩余空间大还是小。为什么要做这样的检查呢?原因很简单,假如 Minor GC 之后 Survivor 区放不下剩余对象,这些对象就要进入到老年代,所以要提前检查老年代是不是够用。这样就有两种情况:

  1. 老年代剩余空间大于新生代中的对象大小,那就直接 Minor GC,GC 完 survivor 不够放,老年代也绝对够放

  2. 老年代剩余空间小于新生代中的对象大小,这个时候就要查看是否启用了「老年代空间分配担保规则」,具体来说就是看-XX:-HandlePromotionFailure参数是否设置了(一般都会设置)
    老年代空间分配担保规则是这样的。如果老年代中剩余空间大小,大于历次 Minor GC 之后剩余对象的大小,那就允许进行 Minor GC。因为从概率上来说,以前的放的下,这次的也应该放的下。那就有两种情况:

  3. 老年代中剩余空间大小,大于历次 Minor GC 之后剩余对象的大小,进行 Minor GC

  4. 老年代中剩余空间大小,小于历次 Minor GC 之后剩余对象的大小,进行 Full GC,把老年代空出来再检查

Minor GC 后的处境
前面说了,开启老年代空间分配担保规则只能说是大概率上来说,Minor GC 剩余后的对象够放到老年代,所以当然也会有万一,Minor GC 后会有这样三种情况:

  1. Minor GC 之后的对象足够放到 Survivor 区,皆大欢喜,GC 结束
  2. Minor GC 之后的对象不够放到 Survivor 区,接着进入到老年代,老年代能放下,那也可以,GC 结束
  3. Minor GC 之后的对象不够放到 Survivor 区,老年代也放不下,那就只能 Full GC

实在不行只能 OOM
前面都是成功 GC 的例子,还有 3 中情况,会导致 GC 失败,报 OOM:

  1. 紧接上一节 Full GC 之后,老年代任然放不下剩余对象,就只能 OOM
  2. 未开启老年代分配担保机制,且一次 Full GC 后,老年代任然放不下剩余对象,也只能 OOM
  3. 开启老年代分配担保机制,但是担保不通过,一次 Full GC 后,老年代任然放不下剩余对象,也是能 OOM
### 垃圾回收(GC过程详解 垃圾回收(Garbage Collection, GC)是 Java 中一种自动化的内存管理机制,其主要目的是释放不再被程序引用的对象所占用的内存空间。以下是关于 GC 的具体过程及其涉及的关键环节: #### 1. **GC 触发条件** GC 并不会随时运行,而是当满足某些特定条件时才会启动。这些条件包括但不限于以下几种情况[^2]: - 当堆中的可用内存不足以分配新对象时。 - 显式的系统调用 `System.gc()` 请求执行 GC(尽管这并不一定会立即触发 GC)。 #### 2. **死亡对象判断方法** 为了有效清理无用对象并释放内存,在 GC 执行之前需要先标记哪些对象是可以被回收的。常见的两种算法用于判定对象是否存活: - **引用计数法**:通过统计某个对象是否有其他对象引用它来决定该对象的状态。然而此方法存在循环引用的问题,因此现代 JVM 不再采用这种方式。 - **可达性分析法**:从一组称为“根节点”的对象出发遍历整个引用链表结构,任何不可达的对象都被视为可回收对象[^3]。 #### 3. **分代假设与分区策略** 基于大多数应用中不同生命周期长度的对象分布特性提出了所谓的“分代假说”,即新生代短命对象多于老年代长期存在的对象。据此将堆划分为以下几个部分: - 新生代 (Young Generation): 主要存储刚创建不久的新实例变量;频繁发生 Minor GC 来清除这部分区域内的废弃数据。 - 老年代 (Old Generation): 存放经过多次Minor GC 后仍然存活下来的较长时间存活对象;只有在必要情况下才进行 Major/Full GC 处理此类较大范围的数据集合。 - 方法区 / 元空间(Metaspace): 记录类元信息,默认较少参与常规意义上的垃圾清扫活动。 #### 4. **日志记录与性能优化** 每次完成一次完整的垃圾收集操作之后都会生成相应的日志条目供开发者查看和诊断潜在问题所在之处。典型的 gc log 包含如下几个方面的内容[^1]: - 时间戳表明何时进行了此次gc动作; - 针对不同类型的具体描述比如 young 或 full gc ; - 收集前后各个子域(eden,survivor0&1以及tenured generation)大小对比数值; - 整体耗时时长等等... 通过对上述各项指标深入剖析可以更好地理解当前系统的实际运作状况进而采取针对性措施提升整体效率表现[^4]. ```python import java.lang.management.ManagementFactory; public class GCDemo { public static void main(String[] args){ Runtime.getRuntime().addShutdownHook(new Thread(() ->{ System.out.println("JVM is shutting down..."); })); while(true){ new Object(); // Create objects continuously to trigger GC eventually. } } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值