1. 前言:
每个java对象都是有生命周期的,就像一个人的生命一样,从孕育到出生到成长变老最后由归于自然。笔者认为,Java对象的整个生命周期可以分为两个大的阶段:即创建阶段和运行阶段(包含对象的回收和消亡)。本篇将会图文深入介绍java对象的整个生命过程。
一般人平时看到java其实只是冰山的一角–java世界的冰上部分,冰下的java世界其实更精彩。
1.java对象的创建阶段
在Java中,对象的创建是一个复杂但有序的过程,涉及多个步骤和底层的JVM(Java虚拟机)运作。java对象的创建过程近似于下图,详细过程如下:
1. 类的加载
其实,在创建对象之前,JVM需要确保类已经被加载、链接和初始化,但这个过程属于对象的孕育阶段,就像一个人在母体一样,所以也是算作对象的创建阶段:
- 加载(Loading):将类的字节码从文件系统中读取到内存中。
- 链接(Linking),又可分为三个阶段:
验证(Verification):确保字节码是合法的,不会违反Java语言的语义规则。
准备(Preparation):为类的静态变量分配内存并设置为默认值(例如,int为0,引用类型为null)。
解析(Resolution):将符号引用转换为直接引用(例如,将方法名转换为方法地址)。 - 初始化(Initialization):执行类的初始化代码,包括静态变量的赋值和静态块的执行。
2. 分配内存
在类加载完成后,JVM会在堆内存中为对象分配空间。实际运作过程如下:
- 判断是否需要线程安全:如果多个线程同时创建同一个类的对象,JVM需要确保内存分配的原子性。这可以通过两种方式实现:
- 使用同步机制:确保每次只有一个线程可以分配内存。
- 使用本地线程分配缓冲区(TLAB,Thread Local Allocation Buffers):每个线程在堆内存中预先分配一块私有空间,用于对象的分配。这样可以减少同步的开销。
- 分配内存:在堆中分配内存空间,具体方式取决于JVM使用的垃圾回收器。例如,在使用Serial GC时,直接分配在Eden区;在使用G1 GC时,根据对象的预期存活时间选择适当的区域。
3. 初始化内存
分配的内存空间初始化为零(基本数据类型,对象引用类型初始化为null)。这一步确保了对象的字段在构造方法执行之前处于确定的状态。
4. 设置对象头
每个对象在内存中都有一个对象头(Object Header),用于存储对象的一些元数据,包括:
哈希码(Hash Code):用于快速查找对象,例如在HashMap中。
GC分代年龄(GC Age):记录对象在垃圾回收过程中经过的次数,用于决定对象是否晋升到老年代。
锁状态标志(Lock Status):记录对象是否被锁定,以及锁的类型(轻量级锁、重量级锁等)。
类元数据指针(Class Metadata Pointer):指向对象的类元数据,用于在运行时访问类信息。
5. 执行构造方法
在对象内存分配和初始化之后,JVM会调用对象的构造方法来完成对象的初始化。构造方法中的代码会设置对象的字段值并执行其他初始化逻辑。
6. 返回引用
构造方法执行完毕后,JVM会将新创建对象的引用返回给调用者。此时,对象已经完全创建并可以使用了。
java对象的运行阶段
- 对象的使用(Usage)
一旦对象被创建并初始化,它就可以被应用程序使用。对象通过其引用变量进行访问和操作。演示如下:
public class Person {
static String period = "GESTATION";
int instanceVar;
static {
// 静态初始化块
System.out.println("这是我的孕育阶段");
}
public void say() {
System.out.println("我就是我,不一样的烟火!");
}
public Person() {
// 构造函数
System.out.println("构造函数被执行");
this.instanceVar = 0;
}
public static void main(String[] args) {
Person person = new Person();
System.out.println("我出生了");
// 可以调用person的say方法
person.say();
}
}
- 对象的垃圾回收(Garbage Collection)
当对象不再被应用程序使用时,JVM的垃圾回收器(Garbage Collector, GC)会自动回收该对象所占用的内存空间。Java使用自动垃圾回收机制,程序员不需要手动释放内存。垃圾回收的判断依据主要是对象的可达性(Reachability),即对象是否从根集合(Root Set)可达。常见的可达性状态包括:
可达(Reachable):对象可以从根集合直接或通过其他可达对象间接到达。
可复活(Resurrectable):对象的所有引用都被释放,但在某个时间点它可能再次变为可达。
不可达(Unreachable):对象既不是可达的,也不是可复活的。这些对象会被垃圾回收器回收。 - 对象的终结(Finalization)
Java提供了一个finalize()方法,允许对象在垃圾回收之前执行清理操作。然而,需要注意的是,finalize()方法并不保证会被及时调用,也不应该被用作主要的清理机制。从Java 9开始,finalize()方法已被弃用,建议使用java.lang.ref.Cleaner和java.lang.ref.PhantomReference来替代。 - 对象的销毁(Destruction)
对象的销毁是指对象所占用的内存空间被垃圾回收器回收的过程。在Java中,对象的销毁是自动进行的,程序员无法直接控制。
本篇完结。
码字不易,宝贵经验分享不易,请各位支持原创,转载注明出处,多多关注作者,家人们的点赞和关注是我笔耕不辍的动力。