HotSpot虚拟机对象探秘

来源:互联网 发布:2015中国进口粮食数据 编辑:程序博客网 时间:2024/05/29 19:07
1、对象的创建
步骤:
(1)虚拟机遇到一条New指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否
已经被夹在、解析和初始化过。如果有那么必须执行相应的类加载过程。
(2)类加载检查通过之后,接来下虚拟机将为新生对象分配内存。
分配方式有两种:“指正碰撞”方式和“空闲列表”方式。
为解决出现正在给A分配内训,指正还没来得及修改,B对象又同时使用了原来的指针来分配内存的情况,有以下两种解决方案:
a、对分配内存空间的动作进行同步处理——实际上虚拟机采用CAS配上失败重试的方式保证更新操作的原子性
b、把内存分配的都陪你工作按照线程划分在不同的空间之中进行,即每个线程在java堆中预先分配一小块内存,称为本地线程分配缓冲(TLAB)
那个线程要分配内存就在那个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定。


(3)内存分配完之后,虚拟机需要将分配到的内存空间都初始化为零值。
(4)接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到累的元数据信息、对象的哈希吗、对象的GC分代年龄等信息,
这些信息存放在对象的对象头中。
(5)执行完NEW指令后会接着执行init()方法,把对象按照程序员的意愿进行初始化,这样一个真正的可用的对象才算完全产生。
2、对象的内存布局
在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头,实例数据和对齐填充。
(1)对象头
对象头包括两部分信息:
a、第一部分用于存储对象自身运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有锁、偏向线程Id、偏向时间戳等
这部分数据长度在32位和64位虚拟机中分别为32bit和64bit,官方称他为Mark Word。Mark Word被设计成一个非固定的数据结构以便在极小的空间内存储
经量多的数据,他会根据对象的状态复用自己的存储空间。
b、第二部分是类型指针,即对象指向他的类元数据的指针,吸泥机通过这个指针来确定这个对象是哪个类的实例。
如果一个对象是java数据,那么对象头重还必须有一块用于记录数组长度的数据,因为虚拟机可以通过java对象的元数据信息确定java对象的大小,但是从数组的元数据中却无法确定
数据的大小。
(2)实例数据
实例数据是对象真正存储的有效信息,也是在程序代码中所定义的各种类型字段内容。
这部分存储顺序会受到虚拟机分配策略参数和字段在java源码中定义的顺序的影响。HotSpot虚拟机默认的分配策略是Longs/doubles、ints、short/char、bytes/booleans、oops
从分配策略上可以看出,相同宽度的字段总是被分配到一起。
(3)对齐填充
对其填充并不是必然存在的,也灭有特别的含义,他仅仅起着占位符的作用。
3、对象的访问定位
目前主流的访问方式有使用句柄和直接只用指针两种。
(1)如果使用句柄访问的话,那么java堆中将会划分出一块内存来作为句柄池,referece中存储的就是对象的句柄地址,而句柄中包含了独享实例数据与类型数据各自的具体地址信息。
好处:reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中实例对象数据指针,而reference本身不需要修改。
(2)如果是使用直接指正访问,那么java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference终存储的直接就是对象的地址。
好处:速度快,它节省了依次指针地位的时间开销。
原创粉丝点击