
va对象通过
new
关键字或反射机制创建。
以下是关于Java对象产生过程的详细内容:
类加载检查与准备
步骤 |
详情 |
符号引用定位 |
当JVM执行引擎遇到new指令时,首先会检查new指令的参数能否在常量池中定位到一个类的符号引用,对于Person person = new Person(); 这样的语句,JVM会在常量池中查找Person 类的符号引用。 |
类加载判断 |
如果在常量池中找到类的符号引用,JVM会进一步检查该类是否已经被加载、解析和初始化,若未加载,则通过类加载器(ClassLoader)将.class文件读入内存,并在方法区中生成对应的类信息,这个过程包括加载(将类的.class文件的二进制数据读入到内存中,并将其转换为一个java.lang.Class对象)、链接(包括验证、准备和解析)以及初始化等阶段。 |
内存分配
步骤 |
详情 |
计算内存大小 |
一旦类加载完成,JVM需要为新建对象分配内存,JVM会计算对象所需内存的大小,这个大小由类的定义决定,包括实例变量所占的空间以及对象头等信息所占的空间。 |
堆内存分配 |
Java堆(Heap)是Java对象存放的主要区域,所有通过new创建的对象都存储在这里,JVM会在堆中为新生对象分配一块连续的内存空间,在分配内存时,JVM可能会使用不同的算法,如指针碰撞法(适用于内存规整的情况,从前往后或从后往前分配内存)或空闲列表法(适用于内存不规整的情况,从空闲列表中找到合适的空间进行分配)。 |
内存空间初始化
步骤 |
详情 |
默认值设置 |
分配完内存后,JVM会将除对象头外的对象内存空间初始化为零值,这一步的目的是确保对象的所有基本类型字段在首次使用时都有一个确定的初始值,比如int初始化为0,boolean初始化为false等。 |
对象头设置
步骤 |
详情 |
设置对象头信息 |
对象头中包含了对象的一些重要信息,如对象的类型、对象的哈希码、对象的锁状态等,JVM会在分配的内存空间中设置这些对象头信息,以便后续对对象进行管理和操作。 |
构造函数执行
步骤 |
详情 |
调用构造函数 |
内存分配和初始化完成后,JVM会调用类的构造函数来初始化新创建的对象,构造函数是类的特殊方法,用于设置对象的初始状态,在构造函数中,可以访问和修改对象的字段,执行必要的初始化逻辑。 |
初始化对象状态 |
通过构造函数的执行,对象的各个实例变量会被赋予具体的值,对象的内部状态得到初始化,从而成为一个完整的、可用的Java对象。 |
引用赋值
步骤 |
详情 |
将对象引用指向内存空间 |
JVM会将new指令创建的对象的引用赋值给变量,在Person person = new Person(); 中,JVM会将新创建的Person对象的引用赋值给变量person,这样程序就可以通过变量person来访问和操作这个Person对象了。 |
相关问答FAQs
问题1:Java对象的创建一定会触发类加载吗?
答:不一定,如果该类之前已经被加载过,那么在创建对象时就不会再触发类加载,只有当第一次创建某个类的对象时,如果类尚未加载,才会触发类加载过程。
问题2:为什么Java对象的内存空间在分配后要进行初始化?
答:Java对象的内存空间在分配后进行初始化是为了确保对象的所有基本类型字段在首次使用时都有一个确定的初始值,避免出现未定义的行为。