JVM之对象

1、对象的创建 虚拟机遇到一条new指令时,首先将检查这个指令参数在常量池中是否能定位到一个类的符号引用,并检查这个符号代表的类是否已被加载、解析和初始化过。如果没有加载必须先执行相应的类加载过程。类加载完成后,JVM将为新生对象分配内存。为对象分配内存等同于把一块确定大小的内存从Java Heap中划分出来。假设JVM内存是规整的,可用指针碰撞来分配如果是不规整,使用和未使用的交错,使用空闲列表来分配。采用那种分配由Java Heap是否规整决定,而是否规整由垃圾收集器是否带有压缩整理功能决定。对象在虚拟机中的创建是非常频繁的,也不是线程安全的,解决此问题有两种方法,同步处理采用CAS失败重试的方式保证更新操作的原子性,另一种是把内存分配的动作划分到不同的控件,即每个线程在Java堆中预先分配一小块内存,TLAB(Thread Local Allocation Buffer),可通过-XX:+/-UserTLAB设定。内存分配完后初始化零值,然后对对象进行必要的设置,把这对象是属于哪个类的实例,如何才能找到类的元数据信息,对象的哈希码、对象的GC分代年龄信息等存放在对象头(Object Header)之中。接着执行方法,把对象按照程序员的意愿进行初始化,对象完成。
2、对象的内存布局 分为对象头、实例数据、对齐填充。对象头包含两部分,第一部分存放运行时数据,如HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等、不同位数操作系统分别是32bit和64bit,官方称为Mark Word。另一部分是类型指针,即对象指向它的类元数据指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。实例数据是真成存储有效信息,也是在代码中定义的各种类型的字段内容。第三部分对齐填充不是必然存在,仅仅是占位,自动内存管理必须是8字节的整数倍,对象头正好是8的倍数(32bit或者是64bit由操作系统决定),而实例数据部分没有对齐时,需要通过对齐填充来补全。
3、对象的访问定位 访问方式有使用句柄和直接指针。Sun HotSpot采用第二种对象访问的,最大的好处是速度快,节省了一次指针定位的时间开销。而第一种好处就是reference中存储的是稳定的句柄,在对象移动的时候只会改变句柄中的实例数据指针,而reference本身不需要修改。

评论已关闭。