概述
通过上一篇博客我们知道了java的内存模型.接下来我们了解一下hotspot虚拟机在java堆中对象的分配、布局和访问的过程
对象的创建
1.类加载检查:遇到一条new指令时首先检查这个指令的参数是否能在常量池中找到这个类的符号引用,并且检查这个符号引用所代表的类是否已经被加载过、解析过、和初始化过。如果没有,那必须先执行相应的类加载过程
2.分配内存:在类加载检查通过后,将在java堆中为新生对象分配内存,分配内存的方法有指针碰撞和空闲列表两种:
- 指针碰撞:适合堆内存规整的情况,把堆内存分为两个部分,一部分是使用中的一部分是未使用的,将指针放在两者的临界处,分配内存的时候向未使用的方向移动相应的距离即可。
- 空闲列表:虚拟机维护一个使用和未使用的列表,分配的时候找到一个足够大的内存空间即可。
3.初始化零值
内存分配完成后,虚拟机将内存空间都初始化为零值(不包括对象头)。保证对象的实例字段在java中不赋值就能够使用
4.设置对象头
对对象记性必要的设置(对象的哈希码、GC分代年龄、元数据信息)
4.执行init()方法
执行init()指令,按照程序员的意愿对对象进行赋值。
对象的内存布局
对象在内存的布局可以分为三部分:对象头、实例数据、对齐填充
对象头包含两部分的信息:一部分是对象自己运行的数据(GC分代年龄、锁标志状态、哈希码)应一部分是类型指针,即指向他的类元数据的指针,确定他是属于哪个类的实例。
实例数据是他真正存储的有效信息
填充数据:占位作用
对象的访问定位
java程序通过java栈的reference数据来操作堆上的具体对象,对象的访问方式有两种,主要的是使用句柄、直接指针。
句柄:根据句柄知道实例数据和类型数据的具体地址(稳定的句柄地址)
reference直接存储对象的地址(速度快)