浅谈Java虚拟机内存中的对象创建,内存布局,访问定位
参考于
深入理解java虚拟机
这里介绍hotspot虚拟机(自带的虚拟机)
1.对象的创建
对于程序员来说,创建对象的方法:
user user1 = new user(); user user2 = new user(04, "tom", 20);
对于虚拟机来说:
1.首先遇到new指令,先去方法区(一块内存,有些人也叫永久代,不过书上说了这种叫法其实不是很准确)检查类有没有加载过了,如果没有,虚拟机去加载,如果加载了,在堆中进行创建。
2.创建对象有两种方法:由虚拟机自己决定,虚拟机自己判断用哪种方法
2.1.如果java堆中都是很规整的:bump the pointer 指针碰撞
红色:原来已经分配了的。 黄色:新创建的。 白色:空的内存。 中间竖线:指针。
根据第1步获得的对象大小,中间指针像空的内存挪动和对象大小相等的一段距离。
2.2.如果堆不规整:free list 空闲列表
红色:原来已经分配了的。 白色:空的内存。 蓝色:一张列表
列表中记录哪块是空的,哪块是空的,然后分配一块合适的用来创建对象,随后更新列表。
2.3.堆是线程共享,虚拟机解决创建对象时线程不安全的方法
第一种,cas保证原子性操作
第二种,tlab本地线程分配缓冲,每个线程都先独占一小块内存,不够了再加,不过再加这个动作需要同步
3.内存分配完成后,内存空间初始化为0(不包括对象头),这也是为什么我们的字段都有一个默认值的原因
4.如果执行的是带参数的构造方法,为参数初始化。
2.对象的内存布局
对象内存布局可分为3块区域:对象头,实例数据,对齐填充
对象头分成两部分:第一部分存放运行时的数据,官方称为“mark word”,这部分的大小和虚拟机的位数有关,虚拟机32位,这部分是32bit,64位同理。
第二部分是类型指针,指针确定这个对象是哪个类的实例。
如果是数组,对象头还包含一块用于记录数组长度的空间
实例数据:对象真正存储的有效信息
对齐填充:类似于占位符,为了让对象为8字节的整数倍。
3.对象的访问定位
两种方式:第一种句柄访问,第二种直接指针访问。hotspot采用第二种,第二种优点是访问速度更快。
第一种:
第二种: