登录
首页 >  文章 >  java教程

Java对象创建与销毁全解析

时间:2026-03-15 18:16:32 330浏览 收藏

Java对象的生命周期远比简单的“new创建、GC销毁”复杂:它可通过new、反射、反序列化等多种方式诞生,其“死亡”却并无确定时刻——一旦失去根可达性即进入可回收状态,但何时被真正清理完全取决于GC策略与JVM配置;finalize已被彻底淘汰,资源释放必须主动靠Cleaner或PhantomReference保障,而文件句柄、网络连接等关键资源更须显式关闭,绝不能寄望于GC“善后”。理解这些底层机制,才能写出真正健壮、无内存泄漏的Java代码。

在Java里对象生命周期是怎样的_Java对象创建与销毁说明

对象什么时候被创建:new、反射、反序列化都算

Java里对象创建不止 new 一种方式。最常见的是 new MyClass(),但还有三种容易被忽略的途径:

  • Class.forName("MyClass").newInstance()(已过时,推荐用 getDeclaredConstructor().newInstance()
  • Constructor.newInstance() —— 反射创建,绕过构造函数访问控制
  • 反序列化:ObjectInputStream.readObject(),不调用任何构造方法,直接分配内存并填充字段

注意:通过反射或反序列化创建的对象,如果类定义了私有构造函数或禁用了默认构造器,仍可能成功(JVM 层面允许),这和 new 的语义不同。

对象何时进入可回收状态:引用计数早被淘汰,得看可达性分析

Java 不用引用计数,而是用根可达性(GC Roots)判断。一个对象只要从 Threadstatic 字段、本地栈变量、JNI 引用等 GC Roots 出发无法到达,就视为“不可达”,进入可回收状态。

常见误判场景:

  • static Map cache = new HashMap<>(); —— 忘记清理会导致对象长期存活,哪怕业务逻辑早已不用
  • 内部类隐式持有外部类引用,比如 new Thread(() -> { doSomething(); }).start(); 中的 lambda 如果捕获了外部 this,可能延长外部实例生命周期
  • 使用 ThreadLocal 后没调用 remove(),在线程池复用场景下会引发内存泄漏

finalize() 已被废弃,替代方案是 Cleaner 或 PhantomReference

finalize() 在 JDK 9 被标记为 @Deprecated,JDK 18 彻底移除。它不可靠、性能差、无法保证执行时机,甚至可能阻止 GC 回收。

现代替代方式只有两个实际可用路径:

  • Cleaner(JDK 9+)注册清理逻辑,例如释放 native 内存或关闭文件句柄:
    private static final Cleaner cleaner = Cleaner.create();
    private final Cleaner.Cleanable cleanable;
    private final FileDescriptor fd;
    
    MyResource(FileDescriptor fd) {
        this.fd = fd;
        this.cleanable = cleaner.register(this, new CleanupAction(fd));
    }
  • PhantomReference + ReferenceQueue 做更底层的资源跟踪,但需自行管理队列轮询,适合框架作者,普通业务极少需要

别再写 protected void finalize() throws Throwable —— 编译器不会报错,但运行时不会调用。

对象真正销毁的时间点:GC 触发后也不一定立刻回收

“销毁”在 Java 中没有明确时间点。对象变为不可达后,只表示“可以被回收”。是否回收、何时回收,完全取决于 GC 算法和 JVM 参数:

  • G1 默认在混合 GC 阶段处理老年代部分区域,不是所有不可达对象都会在这次被清掉
  • ZGC 和 Shenandoah 是并发收集器,对象可能在应用线程还在读写时就被标记为待回收,但内存真正归还给操作系统可能延迟数秒甚至更久
  • 即使触发了 System.gc(),也仅是建议,HotSpot 默认配置下大概率被忽略(尤其在 Server VM)

真正要注意的不是“销毁时间”,而是“资源释放时机”。文件、Socket、DirectByteBuffer 这些必须显式 close()clean(),不能依赖 GC。

到这里,我们也就讲完了《Java对象创建与销毁全解析》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

资料下载
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>