首先JVM遇到new指令,会检查指令参数可否在常量池中定位到一个符号引用。而且检查这个符号引用所表明的类是否已被加载、解析和初始化过。若是没有会进行相应的类加载过程。布局
类加载验证经过后,为新生对象分配内存。spa
内存分配完成后,JVM须要将分配到的内存空间都初始化为零。这一步操做保证了对象的实例字段在Java代码中能够不赋初始值就直接使用。线程
对对象进行必要的设置,例如这个对象是哪一个类的实例,如何才能找到类的元数据信息,对象的Hash码值,对象的GC分代年龄等信息。这些信息都放在对象头中,grn指针
上述工做完成后,对虚拟机而言一个新的对象已经产生。从Java程序而言对象的建立刚刚开始。根据当前虚拟机运行状态的不一样,如是否启用偏向锁等,对象头都会有不一样的设置。对象
在HotSpot中,对象在内存中的布局分为3块区域:继承
包含两部分数据:内存
用于存储对象自身运行时数据,如Hash码、GC分带年龄、锁状态标志、线程持有的锁等源码
另一部分是类型指针,即对象指向它的类元数据指针,经过这个指针肯定对象是哪一个类的实例。(并非全部的虚拟机都在对象数据上保留类型指针)虚拟机
是对象真正存储的有效信息,也就是程序代码中所定义的各类类型的字段内容。不管父类继承仍是子类定义都要记录,这部分数据受虚拟机分配策略参数和Java在源码中的定义顺序影响。内存管理
仅仅起着占位符的做用,并非必要的,也无心义。(例如Hot Spot自动内存管理系统要求对象起始地址必须是8字节的证书倍,须要对齐填充来补全)
Java程序须要经过栈上的reference数据来访问堆中的具体对象,reference类型在JVM中只规定了一个指向对象的引用,并无定义这个引用经过何种方式去定位,访问堆中对象的具体位置。对象的访问方式取决于JVM的实现方式。
主流方式:
使用句柄
Java堆会划分一块内存做为句柄池,reference中存储的是句柄地址,而句柄中包含了对象的实例数据和类型数据的具体地址信息。
直接访问
reference存储的直接就是对象地址。
优缺点:
使用句柄最大的好处是reference中存储的是稳定的句柄地址,在对象被移动时只改变du句柄中的实例数据指针,而reference不须要修改。
使用直接地址最大的好处是速度更快,节省了一次指针的定位开销。