缺点,浪费了空间
现在的虚拟机实现的, 等新生代收集器就是这种内存布局;把新生代划分成Eden区域和两块 ;比例是8:1:1;
Minor GC 的时候把Eden 和存活的对象复制到一块保留的 上面,清除Eden 和 ;如果保留的 内存不够保存存活的区域,就需要老年代担保
3.4 标记-整理算法
Mark- :标记复制对于存活率较高的区域清除效率相对就比较低下,而且还需要浪费空间和空间担保;如果是内存全部存活的老年代那种回收 对象100%存活 。
算法实现:标记过程 和 标记-清除 一样,但是后面是让存活对象向内存一边移动,然后直接清除以外的内存;
如何移动对象,特别是在老年代都是在使用中的对象,对象在内存区域内的移动是比较重的操作,虚拟机会停止用户程序的执行,成为 STD stop the world
为什么要移动对象,是为了保证内存空间的连续性,提示虚拟机吞吐量;要是移动对象,停顿时间会更短,甚至不停顿;
关注吞吐量的实现
关注低延迟的实现 使用标记-清楚实现 CMS
4. 的算法实现细节 4.1根节点枚举
收集器的根节点枚举是需要暂停用户线程的,不能在节点枚举过程中出现因为用户线程发送变动,,保证分析结果的可靠性,会有STD stop the world,但是可达性分析算法可以和用户线程一起执行;
在 的实现方案里面,是有 数据结构来存储执行上下文和全局引用;
4.2 安全点
有了 可以快速完成 GC Roots 根节点枚举,但是很多代码指令会影响到 的关系,如果每一个指令都去关联一下 ,难免加大运行成本和存储成本;只是在特定的时候记录到 ,这些位置被称为安全点 ,每个指令执行都很短暂,一般选择‘长时间指令’ 比如方法调用,循环跳转,异常跳转,这些才会有安全点;
如何保证程序运行到代码附加的安全点来停顿,有两种实现方案:
抢先式中断,,不需要线程的执行代码主动配合,GC 时,全部停止,然后把还没有到安全点的线程恢复执行,知道最近的安全点,现在很少使用了主动式中断,,垃圾回收需要停止线程的时候,不需要对线程操作,设置一个标志位,用户线程在执行的时候(轮询的时间点:安全点+ 创建对象+ 堆内存分配内存)去轮询这个标志位,发现中断标志位就在最近的安全点上面主动挂起; 轮训指定 test 4.3 安全区域
Safe安全点事正在执行的线程响应线程中断指令,但是用户线程处于Sleep / 状态 这个时候就无法主动响应中断了,这个时候就引入了安全区域;线程在执行到安全区域时候,垃圾回收器不会管理这些进入了安全区域的线程,等这些线程恢复的时候,如果还没有完成根节点枚举,就保持运行,一直在安全区域运行,直到枚举完成,可以离开安全区域;
4.4Set
前面说了Set 是记录跨代引的对象;避免全量扫描老年代;本小节主要是介绍 Set 的实现方式;若不考虑性能的话,最简单的实现就是非收集区域中所有含跨代引用对象的数组,这样也是新能比较低下的;
有三种记录方式
Card Table最简单的实现就是字节数组(不用bit 是因为现在计算机硬件指令最小都是byte),而也是这样实现的
CARD_TABLE[this addredd >> 9 ] = 0
数组内部一个对象标识者内存区域一块内存(卡页 Card Page ,大小一般是2^n 幂的字节数 上面可以看到是 9 次方 512 字节),
比如其实地址是下面就是映射关系 , 如果 Card Page 记录的是1 就是标志着对应的内存区域是Dirty 是有跨代引用的,加入 GC Roots
4.5 写屏障
卡表元素如何维护: 何时变脏:其他区域引用了本区域,时间点就是引用对象赋值的那一刻;如何变脏:如何在赋值的时候去维护卡表;
- JAVA的垃圾收集器与内存分配策略【一篇文章直接看懂】
- 二 Android——数据持久化技术 SharedPreference存储
- 二、Redis持久化
- 二 JavaWeb——Servlet入门
- 二 零基础学习WEB前端开发:HTML标签及开发工具
- 二、HashMap和WeakHashMap的区别
- 二 UI自动化进销存系统之会员管理
- 视频行为理解之二
- 架构 ThinkPHP5文档学习笔记--
- 二 Django入门