内存分配:
为对象分配内存有两种方式,第一种是“指针碰撞”,也就是把内存分为两边,一边是已使用区域,另一边是未分配区域,分界线用指针记录,当要分配内存时,只需把指针向未分配区域移动需要的空间即可,通常compact算法的垃圾回收会使用“指针碰撞”,如Serial、ParNew;另一种是空闲列表记录,也就是分配是可以不连续的,中间很多间隔可用的未分配内存,这个时候需要一个列表来对内存进行记录,分配内存时候就在列表找到最合适的,通常这种分配方式对应的垃圾回收器如CMS这种基于Mark-Sweep算法;
由于分配内存也是多线程,存在内存使用资源的竞争,因此要保证线程安全,解决这个问题有两种方案,第一种是利用CAS加上失败重试方法保持原子性;第二种是用到ThreadLocal思想,就是为每一个线程分配一个线程自己的空间,称为Thread Local Allocation Buffer,TLAB,当线程完成逃逸分析后就把对象分配到该区域内。最后,当线程分配完后虚拟机就马上为分配到的空间初始化为零值,不包括对象头。
对象头(Header):
对象可以分为三部分,对象头、实例数据、对齐填充;
对象头包括两种信息,第一是运行时数据(Mark Word),第二是类型指针(用作指定该对象是哪个类创建的,但也不一定就这样实现);运行时数据包括:哈希吗、GC分代年龄、锁状态标志、线程持有的锁、偏向锁ID、偏向时间戳等等。如果该对象是数组,那么还会对象头还会继续数组大小的数据。
然后就是真正的实例数据了,实例数据包括父类继承下来的和子类拥有的,会优先安排父类的字段排序在前面,同时会根据基本类型的大小,把大小相同的放到一起分配。最后的数据对齐就是简单的填充作用。
、、、、、待续
原文:https://www.cnblogs.com/iCanhua/p/8904823.html