Java作为一门自动内存管理的编程语言,对象生命周期管理与垃圾回收机制是其核心特性之一,理解这部分内容能帮助开发者更清晰地认知JVM的内存运作逻辑,写出更稳健的代码。

Java对象的完整生命周期阶段
Java对象从被创建到最终被销毁,会经历多个明确的阶段,每个阶段都有对应的JVM处理规则:
- 创建阶段:当程序执行到
new关键字或者反射、反序列化等创建对象的逻辑时,JVM会在堆内存中分配对应的空间,完成对象的初始化,此时对象进入可用状态。 - 应用阶段:对象被创建后,只要有强引用指向它,就可以被程序正常使用,这是对象生命周期中最长的阶段。
- 不可达阶段:当所有指向该对象的强引用都被释放,对象不再被任何存活的线程引用时,就会进入不可达状态,此时对象已经无法被程序访问。
- 可收集阶段:JVM的垃圾回收器已经标记该对象为可回收状态,但是还没有开始执行回收操作,此时对象还有可能通过finalize方法重新被引用,回到应用阶段。
- 终结阶段:对象的finalize方法已经被调用,并且没有重新建立引用,此时对象已经确定会被回收。
- 释放阶段:垃圾回收器正式回收该对象占用的内存空间,对象彻底从内存中消失。
垃圾回收的核心判断规则
JVM要判断一个对象是否可以被回收,核心依赖两个规则:
引用计数法
给每个对象添加一个引用计数器,每当有一个地方引用该对象时计数器加1,引用失效时减1,当计数器为0时说明对象不再被引用,可以被回收。但是这种方法无法解决循环引用的问题,比如两个对象互相引用,但是没有外部引用指向它们,计数器永远不会为0,就会导致内存泄漏,所以主流的JVM不会单独使用这种方法。
可达性分析算法
这是主流JVM使用的判断规则,核心思路是以GC Roots作为起点,向下搜索所有引用的对象,搜索走过的路径称为引用链。如果一个对象到GC Roots没有任何引用链相连,就说明这个对象是不可达的,可以被回收。常见的GC Roots包括:
- 虚拟机栈中局部变量表引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
常见的垃圾回收算法
确定可回收对象之后,垃圾回收器会使用不同的算法来完成内存回收,常见的算法有以下几种:
| 算法名称 | 核心逻辑 | 优缺点 |
|---|---|---|
| 标记-清除算法 | 先标记所有需要回收的对象,标记完成后统一回收所有被标记的对象 | 优点是实现简单,缺点是会产生大量内存碎片,可能导致后续大对象无法分配内存 |
| 标记-复制算法 | 将内存分为大小相等的两块,每次只使用其中一块,回收时将存活对象复制到另一块,然后清理当前块的所有对象 | 优点是不会有内存碎片,缺点是内存利用率只有50%,适合存活对象少的场景比如新生代 |
| 标记-整理算法 | 标记过程和标记-清除一致,之后让所有存活对象向一端移动,然后直接清理掉边界以外的内存 | 优点是没有内存碎片,内存利用率高,缺点是移动对象会有性能开销,适合老年代场景 |
| 分代收集算法 | 根据对象存活周期的不同将内存分为新生代和老年代,新生代用标记-复制算法,老年代用标记-清除或者标记-整理算法 | 优点是结合了不同算法的优势,是当前主流JVM的默认回收策略 |
代码示例:观察对象生命周期与垃圾回收
我们可以通过简单的代码来观察对象的回收过程,注意需要重写finalize方法才能看到对象被回收的提示,但是finalize方法在Java9之后已经被标记为废弃,实际开发中不建议使用:
public class ObjectLifeCycleDemo {
// 重写finalize方法,对象被回收前会调用这个方法
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("对象被垃圾回收器回收了");
}
public static void main(String[] args) {
// 创建对象,此时对象进入应用阶段
ObjectLifeCycleDemo demo = new ObjectLifeCycleDemo();
// 释放引用,对象进入不可达阶段
demo = null;
// 主动触发垃圾回收,注意这只是建议JVM执行回收,不保证一定立即执行
System.gc();
// 休眠一段时间等待回收执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行上面的代码,大概率会输出"对象被垃圾回收器回收了"的提示,说明对象已经被成功回收。如果我们在将demo赋值为null之后,又重新给demo赋值一个新的引用,那么对象就不会被回收。
开发中的注意事项
理解对象生命周期和垃圾回收之后,开发中要注意避免不必要的内存泄漏:
- 及时释放不再使用的对象引用,比如将集合中的无用对象移除,或者将对象引用赋值为null
- 谨慎使用静态变量,静态变量的生命周期和类一致,如果静态变量持有大对象的引用,会导致对象一直无法被回收
- 避免在finalize方法中做复杂的操作,因为finalize方法的执行时间不确定,还可能影响垃圾回收的效率
- 合理设置JVM的堆内存参数,根据应用的实际内存使用情况调整新生代和老年代的大小,减少频繁的垃圾回收
Java对象生命周期垃圾回收GC算法JVM内存管理修改时间:2026-06-27 00:48:19