对象创建
虚拟机遇到对象创建指令时,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,检查该类是否被加载、解析和初始化过,如果没有先执行类的加载过程。
类加载检查通过后,为新生对象进行内存分配。
内存分配方式
指针碰撞
对于java堆中内存时绝对规整的,使用过的内存在一边空闲的内存在另一边,中间放一个指针作为分界点指示器,分配内存时 只需要把指针移动对象大小相等的距离。
空闲列表
对于java堆中内存不是规整的,虚拟机用一个列表记录那块儿内存可用,为对象分配内存时,找到一块足够大的空间画风诶对 象,同时更新列表。
分配内存并发方案
CAS同步处理
本地线程分配缓存
把内存分配的动作按照线程划分到不通的空间上进行,即每个线程在java堆中预先分配一块内存。
虚拟机启用本地线程分配缓存可以通过-XX:+/-UserTLAB
对象内存布局
对象头
运行时数据Mark Wrod
存储哈希码、GC分代年龄、所状态标志、线程持有的锁、偏向线程id、偏向时间戳
这部分数据官方称为 Mark Word,其为一个非固定的数据结构以便在绩效的空间内存存储尽量多的信息。
类型指针
即对象指向它的类元数据的指针,通过这个指针来确定该对象是那个类的实例。
实例数据
程序代码中定义的各种类型的字段内容。
对齐填充
对象的访问定位
使用句柄
java堆中划分一块内存作为句柄池,reference中的地址就是句柄地址,句柄包含了对象的实例数据和类型数据的具体地址。
优点:reference中存储的是稳定的句柄地址,对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要修改
直接指针
java对象的布局中考虑如何放置访问类型数据的相关信息,reference中存储的直接就是对象地址。
优点:访问速度快,节省了一次指针定位的时间开销。