java对象在执行new表达式时创建,包括构造方法初始化;gc通过可达性分析判定不可达对象可回收,但销毁时间不确定,关键资源须用try-with-resources或显式close()释放。

Java对象什么时候被创建
对象在执行 new 表达式时才真正创建,包括调用构造方法完成初始化。注意:类加载、静态字段赋值、静态代码块执行都发生在对象创建之前,不等于对象诞生。
常见误判点:
- 声明引用变量(如
MyClass obj;)不触发创建 -
Class.forName("MyClass")只加载类,不创建实例 - 反序列化(
ObjectInputStream.readObject())会绕过new和构造方法,但仍算一次对象创建
GC如何判断一个对象可以被销毁
Java 不提供显式“销毁”操作,对象生命周期终结由垃圾收集器(GC)决定。判定依据是“可达性分析”:从 GC Roots 出发,不可达的对象被视为可回收。
GC Roots 通常包括:
立即学习“Java免费学习笔记(深入)”;
- 虚拟机栈中引用的对象(局部变量)
- 本地方法栈中 JNI 引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象(如字符串常量池中的
"abc")
注意:finalize() 方法已被标记为 @Deprecated,且不保证执行时机与次数,绝不能用于释放关键资源(如文件句柄、数据库连接)。
手动干预对象生命周期的常见陷阱
开发者常试图“提前结束”对象生命,但多数做法无效或有害:
- 将引用设为
null(如obj = null;)仅在特定场景有用(如长生命周期容器持有短生命周期对象),对局部变量几乎无意义 - 调用
System.gc()仅是建议,JVM 可忽略;现代 GC(如 G1、ZGC)已不依赖此调用 - 使用
WeakReference/PhantomReference是合理手段,但需配合ReferenceQueue使用,否则容易内存泄漏(如未及时清理队列中已入队的引用)
典型错误示例:WeakReference<myobj> ref = new WeakReference(obj); obj = null;</myobj> —— 这里 obj 原本就是局部变量,清空它并不影响弱引用本身的语义,反而可能掩盖真实持有关系。
对象实际销毁时间永远不确定
即使对象已不可达,JVM 也可能因内存充足而长期不触发 GC;即使触发 GC,不同收集器行为也不同(如 ZGC 几乎并发回收,而 Serial GC 会 Stop-The-World)。你唯一能控制的是“何时让它变得不可达”,而不是“何时被回收”。
真正需要确定性清理的资源(I/O、锁、native 内存),必须用 try-with-resources(实现 AutoCloseable)或显式 close(),不能依赖对象回收。









