2 Java内存层面的对象认识


说明:此分析基于HotSpot虚拟机

1 对象的创建

Java对象的创建方式有三种:

  1. 通过new创建
  2. 通过反序列化创建
  3. 通过复制创建

通过new方式的对象创建过程如下:

创建过程说明:

  1. 执行字节码遇到new指令时,首先将去检查这个指令的参数是否能在常量池中定位到 一个类的符号引用。
  2. 类的初始化过程在后续章节详细补充
  3. 给对象分配初始内存空间有两种方式:指针碰撞 和 空闲列表。
  4. 分配空间后,清空该段的【不包括对象头】值,保证对象属性的不设值就使用初始值
  5. 对象头信息包括:元数据信息、对象的哈希码、对象的GC分代年龄
  6. 执行构造函数,给属性初始化设置的值

2 对象的内存布局

对象存储的内容分类以及明细如下:

一、关于对象头的补充说明

  1. 对象头,在字长为32位和64位的虚拟机中分别为32比特(4字节)64比特(8字节)。
  2. 对象头的类型指针:不一定所有对象都会存储这项信息,意味着访问对象所属的类不一定通过对象自身。
  3. 如果对象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据。

二、关于实例数据的补充说明

  1. 对象属性的存储顺序,受到虚拟机分配策略参数(-XX:FieldsAllocationStyle参数)和字段在Java源码中定义顺序的影响
  2. 默认的分配策略下:占据相同字节数的属性会排列在一起,满足该条件下,父类的属性排在前面。

三、关于对齐填充的说明

  1. 不一定会存在,因为对象的大小一定是8字节的整数倍,因此需要对齐填充这部分,充当占位符

在32位字长的虚拟机下,对象的内存分布情况如下:

对象头的MarkWord部分

注:MarkWord结构在《synchronized详解》会涉及

3 对象的访问定位

对象访问方式也是由虚拟机实现而定的,主流的访问方式主要有使用句柄直接指针两种:

3.1句柄访问

说明:
句柄访问方式,Java堆中将可能会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据类型数据各自具体的地址

3.2 直接指针访问

说明:
使用直接指针来访问最大的好处就是速度更快,只需要一次定位就能找到实例数据,而句柄池则需要两次:(需要先定位句柄池,再定位实例数据)

posted @ 2022-09-19 16:51  拿了桔子跑-范德依彪  阅读(108)  评论(0编辑  收藏  举报