在Java虚拟机中,当类加载检查通过后,即对象创建时,需要分配内存。内存分配的方式有两种:指针碰撞和空闲列表。
-
指针碰撞:
- 适用场合: 适用于堆内存规整,即没有内存碎片的情况。
- 原理: 将已经使用的内存整合到一边,未使用的内存放在另一边,中间有一个分界指针。对象的分配只需将分界指针向未使用的内存方向移动对象大小的位置。
- 使用该分配方式的GC收集器: Serial, ParNew
-
空闲列表:
- 适用场合: 适用于堆内存不规整的情况,即存在内存碎片。
- 原理: 虚拟机维护一个列表,记录哪些内存块是可用的。在分配时,会找到一块足够大的内存块,划分给对象实例,并更新列表记录。
- 使用该分配方式的GC收集器: CMS
内存分配并发问题:
- CAS+失败重试: 使用CAS(Compare And Swap)配上失败重试的方式保证更新操作的原子性。CAS是一种乐观锁的实现方式,假设没有冲突,如果失败就重试,直到成功。
- TLAB(Thread Local Allocation Buffer): 为每一个线程预先在Eden区分配一块内存。JVM在给线程中的对象分配内存时,首先在TLAB中分配。当对象大于TLAB中的剩余内存或者TLAB的内存已用尽时,再采用CAS进行内存分配。
这些策略和机制旨在提高内存分配的效率和并发性,适应多线程环境下的对象分配需求。