额外概念了解
jvm内存空间是逻辑上连续的虚拟地址空间(虚拟内存中的概念)映射到物理内存(不一定连续),物理内存不足时还会将物理内存中的数据交换到swap(磁盘的一块区域)。这块水有点深,查阅资料做了个个人的总结。
内存划分,有指针碰撞和空闲列表这两种划分方式:
1、指针碰撞
当内存区域规整排列,也就是说已用内存放在一边,空闲内存放在一边,中间用指针作为分界点,在给新的对象分配内存时,可以将指针向空闲端移动对象大小的距离。碰撞是由于指多线程访问时,因内存共享,会存在内存冲突(指针碰撞)的情况,当然可以使用CAS和TLAB两种方式解决
2、空闲列表
当内存区域不规整排列,已用内存和空闲内存交错,此时无法通过指针碰撞划分内存,jvm通过维护一个空闲列表,用来记录空闲内存区间,新对象内存分配时,找到一块足够大的内存空间去分配,并更新空闲列表。
3、那么指针碰撞和空闲列表的使用时机是什么,或者说什么时候内存区域规整或者不规整呢?
不同GC垃圾回收器有不同垃圾回收算法,对于标记-整理算法,内存区域是规整的。而标记-清除算法,内存区域是不规整的。因此也验证了为何标记清除算法会产生内存碎片的问题。
jmm内存模型说明
jmm内存模型中有工作内存(本地内存)和主内存两个概念
- 工作内存是一个抽象概念,由每个线程独享,实际指的是cpu寄存器与缓存,并不是真正的内存条中的内存。线程栈和栈帧属于工作内存的概念范畴。
- 主内存区域被多线程共享,是真正的内存条中的内存,堆属于主内存概念范畴。
- 线程对变量的操作在工作内存完成再写入到主内存中
- 实例对象的成员变量无论是基础类型还是引用类型都是存储在堆区
- 实例对象的成员方法中的基础变量存储在栈帧中,引用类型存储在堆中
- 实例对象的静态变量存储在堆中,类本身信息存储在主内存中(元空间)