对象分配内存时的指针碰撞与空闲列表机制
上一节我们说了创建一个对像的流程
加载类---->类加载检查------>内存分配----->初始化零值----->设置对象头----->执行
这一节我们说一下,内存是怎么分配的,并且再分配的过程中如何解决并发问题
1.指针碰撞(Bump the Pointer)(默认用指针碰撞)
如果java堆中的内存是绝对规整的,所用的用过的内存放在一边,所有没有用过的内存放在另外一边,中间放着一个指针作为分界点,再分配内存的时候,我们首先计算出来对像所需内存大小,之后我们把指针向空闲空间挪对像内存的大小就可以了
2.空闲列表(Free List)
如果java堆中的内存并不是规整的,已使用的内存和未使用的内存是交错的,那就没有办法用指针碰撞这种简单的把指针挪一下就把内存分配的方法了,虚拟机就必须维护一个列表,记录哪些列表是可用的,在分配的之后从列表中找一块大于等于对像大小的一块空间,划分给对像,并更新列表上的记录
在以上内存分配的时候会有并发的问题,再分配A内存的时候还未来得及更新指针或者列表,对像B又同时过来分配内存了,这个时候对像B是不知道内存的最新情况的。。。这又问题有CAS与TLAB这两种解决方法:
1.CAS(compare and swap)
虚拟机采用CAS配上失败重试的方式保证更新操作的原子性来对内存分配空间动作进行同步处理。
2.TLAB 本地线程分配缓冲(Thrad Local Allocation Buffer,)
把内存分配的动作按照线程划分为不同的空间之中进行,即每个线程在Java堆中预先分配一小块内存。
通过-XX:+/-UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开始-XX:+/-UseTLAB),-XX:TLABSize指定TLAB的大小