实例化对象过程

实例化对象过程

new关键字执行过程

  1. 进行类加载检查。当遇到一个new指令,首先检查能否在方法区的常量池中能否定位到这个类的符号引用,并且检查类有没有进行加载、解析和初始化

  2. 进行类加载检查。当遇到一个new指令,首先检查能否在方法区的常量池中能否定位到这个类的符号引用,并且检查类有没有进行加载、解析和初始化

  3. 初始化。将分配的内存初始化为0值

  4. 基本设置。进行基本的设置,确定这个对象是哪个类的实例,对象的HASH码,对象的年龄等等

对象内存布局

  1. 对象头(Header)
    对象头包含两个部分的信息,第一部分是对象自身的运行时数据,如哈希码、GC分代年龄、持有的锁等等;第二部分是类型指针,指向它的类元数据的指针,通过这个虚拟机来确定这个对象是哪个类的实例。

  2. 实例数据(Instance Data)
    对象真正存储的数据,就是程序代码中定义的字段内容。

  3. 对齐填充(Padding)
    用于使对象的开头必须是8字节的整数倍,无特殊意义。

对象的访问定位

Object objectRef = new Object();

Object objectRef 这部分将会反映到Java栈的本地变量中,作为一个reference类型数据出现。而“new Object()”这部分将会反映到Java堆中,形成一块存储Object类型所有实例数据值的结构化内存,根据具体类型以及虚拟机实现的对象内存布局的不同,这块内存的长度是不固定。另外,在java堆中还必须包括能查找到此对象类型数据(如对象类型、父类、实现的接口、方法等)的地址信息,这些数据类型存储在方法区中。

有两种基本的定位方式:

第一:句柄访问(间接)
在Java堆中划分一块内存作为句柄池(即一个句柄列表),reference中存储的就是对象在句柄池中的地址,得到了句柄池的地址就可以知道对象的实例数据和类型数据的位置。

image

第二:直接指针访问(直接)

reference中存储的直接就是对象的实例数据的地址,而实例数据中自己有一个指针存储对象类型数据的地址(方法区中),不需要reference来存储。

image

你可能感兴趣的:(实例化对象过程)