对象的创建
在代码层面我们看到对象的创建就是一个new但是这里我们在虚拟机的角度看对象创建的过程。
-
1:在虚拟机遇到一条new指令时,首先检查这个指令的参数能否在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已经被加载,解析和初始化过。如果没有那必须先执行相应的类加载过程。
-
2:类加载检查通过后,虚拟机为新生对象分配内存。
堆分配内存时两种方式:(1)指针碰撞:假设队堆内存绝对规整,用过内存放在一边,没用过的内存放在另外一边,中间放一个指针指示指示器。(2)空闲列表:堆中内存不规整,维护一个列表,列表存储堆中空闲的内存。 -
3:将虚拟机给对象分配到的内存空间初始化为零,保证对象实例字段在未赋初始值情况下可以使用。
-
4:对对象进行一些必要的设置。
对象的内存布局
在HotSpot虚拟机中对象布局可以分为三个区域是:对象头,实例数据,对象填充。
对象头包括:类型指针(对象指向它类元数据的指针,虚拟机通过这个指针确定对象是哪个类的实例),对象自身运行时数据就是MarkWord()
实例数据部分是对象真正存储信息的地方,
对其填充不是必须部分,起到占位符的作用
对象访问定位
Java中通过栈中的reference来操作堆上对象的具体数据。虚拟机中reference只规定了一个指向对象的引用,并没有规定以各种方式去定位,访问堆中对象的具体位置,所以对象的访问方式取决于虚拟机的具体实现,目前主流的访问方式两种,句柄式和直接指针式。
- 句柄式
- 直接指针式
它们各有各的优点
句柄式优点:reference中存储的是稳定的句柄地址,所以在对象移动时改变是对象实例数据指针。
直接指针式:优点就是快,节省指针定位的开销。