垃圾回收器
2021-10-10 15:30:03 0 举报
Java 中各个垃圾回收器知识点详解
作者其他创作
大纲/内容
Serial Old 是 Serial 收集器的老年代版本,同样是一个单线程收集器,主要意义也是在客户端模式下的 HotSpot 虚拟机使用在服务端模式下主要用途:JDK 5以及之前的版本中与 Parallel Scavenge 收集器搭配使用;作为 CMS 收集器发生失败时的后备预案,在并发收集发生 \"Concurrent Mode Failure\" 时使用;
安全点
用户线程
标记 GC Roots 能直接关联的对象,并修改 TAMS 值,需要 STW
指向新的引用
老年代采用整理算法暂停所有用户线程
用于出来并发阶段结束后遗留下来的 STAB 的记录,需要 STW
Region 1
Region 2
Region 3
Region 4
Region 5
老年代
GC 线程
Shenandoah
Parallel Old 是 Parallel Scaenge 收集器的老年代版本,支持多线程并发收集,基于标记整理算法适合在注重吞吐量或者处理器资源较为稀缺的场合使用
老年代和新生代
小型 Region
中型 Region
大型 Region
筛选回收
JDK 9 取消组合支持
重新标记
JDK 5以及之前搭配使用
E
S
O
老年代采用标记-整理算法,暂停所有用户线程
Humongous
ZGC 收集器是一款基于 Region 内存布局的,(暂时) 不设分代,使用了读屏障、染色指针和内存多重映射等技术来实现可并发标记-整理算法的,以低延迟为首要目标的一款垃圾收集器。
Object Address(42bit,4TB address space)
Header
更新 Region 的统计信息,对 Region 的回收价值和成本排序,制定回收计划。需要 STW
使用内存映射解决修改指针后操作系统。处理器不支持的情况Linux/x86-64 平台上的 ZGC 使用多重映射将对个不同的虚拟内存地址映射到同一个物理内存地址上,这是一种多对一的映射。把染色指针的标志位看作是地址的分段符,那只要将这些不同的地址段都映射到同一个物理内存空间,经过多重映射转换后,就可以使用染色指针进行正常寻址
CMS
最终标记
G1 主要是面向服务端的垃圾应用器G1 认为只要大小超过了一个Region 容量一半的对象即可判定为大对象,大对象存储在 Humongous 中,对于超过了整个 Region 的超级大对象,会放在 N 个连续 Humongous 中G1 可以控制收集的停顿时间主要是维护了一个优先级列表,每次会优先处理价值(回收所获得的空间和回收所获得时间的经验值)最大的 RegionG1 为每个 Region 设计了两个名为 TAMS 的指针,把 Region 中的一部分空间划分出来用户并发回收过程中的新对象分配,并发回收时新分配的对象地址都必须要在这两个指针之上记忆表的结构:Key 是别的 Region 的起始地址,Vlaue 是一个集合,里面存储的元素是卡表的索引G1 从整体看是标记整理算法,从局部(两个 Region 之间)上看是标记复制算法
Foo
新生代采用复制算法暂停所有用户线程
断开
初始标记
Serial Old(MSC)
Parallel Old
Brooks Pointer
新生代
修正并发期间,因用户线程继续运行导致标记产生变动的那些对象的标记记录(增量更新),需要 STW
连接矩阵可以理解为一张二维表格,如果 Region N 有指向对象指向 Region M,就在表格的 N 行 M 列中打上一个标记
ParNew
Parallel Scavenge 收集器的目标是达到一个可控的吞吐量吞吐量 = 用户运行代码时间 / (用户运行代码时间 + 运行垃圾收集时间)高吞吐量可以最高效率的利用处理器资源尽快完成运算任务,适合在后台运算而不需要太多交互的分析任务
Region Number
1
2
3
4
5
6
Bar
并发标记
染色指针优势:染色指针可以使得一旦某个 Region 的存活对象被移走之后,这个 Region 立即就能够被释放和重用掉,而不必等待整个堆中所有指向该 Region 的引用被修改后才能清理染色指针可以大幅减少在垃圾收集过程中内存屏障的使用数量,设置内存屏障,尤其是写屏障的目的通常是为了记录对象引用的变动情况,如果将这些信息直接维护在指针中,可以省去一些专门的记录操作染色指针可以作为一种可扩展的存储结构用来记录更多与对象标记、重定位过程相关的数据,有利于日后提升性能。
Serial
G1
ParNew 实质上是 Serial 收集器的多线程并行版本,除了同时使用多条线程进行垃圾收集之外,其余的行为包括 Serial 收集器可用的所有控制参数、收集算法、STW、对象分配规则、回收策略等都与 Serial 完全一致。除了 Serial 收集器之外,目前只有 ParNew 能与 CMS 收集器配合工作JDK 9 开始 ParNew + CSM 不再是官方推荐的服务端模式下的收集器解决方案
重置线程
小型 Region:容量固定为 2MB,用于放置小于 256K 的小对象中型 Region:容量固定为 32MB,用于放置大于等于 256KB 但小于 4MB 的对象大型 Region:容量不固定,可动态变化,但必须是 2MB 的整数倍,用于放置 4MB 或以上的大对象。每个大型 Region 中只会存放一个对象,实际容量可能小于中型 Region,最小容量可低至 4MB
后备预案
清楚标记阶段判断已经死亡的对象
单线程串行 GC,在进行垃圾收集时,必须暂停是所有的工作线程。算法:标记-复制算法客户端模式下默认新生代收集器对于其他收集器,Serial 收集器简单高效,在内存资源首先环境中,它是所有收集器中额外内存(保证垃圾回收器能顺利高效进行而存储的额外信息)消耗最小的
ZGC 堆内存布局
染色指针
Shenandoah 的目标是实现一种在任何堆内存大小下都可以把垃圾收集的停顿时间限制在 10 毫秒以内,所以它不仅要进行并发的垃圾标记,还要并发的进行对象清理后的整理动作。Shenadoash 相对于 G1 的不同点: 1.支持并发的整理算法,可以实现回收阶段与用户线程并发执行; 2.Shenadoash 默认不使用分代收集,意味着不会有新生代 Region、老年代 Region; 3.摒弃了 G1 中的记忆集,改用 \"连接矩阵\" 的全局数据结构来记录跨 Region 的引用关系,降低了处理跨代指针时的记忆集维护消耗,降低了伪共享问题发生概率;
Parallel Scavenge
Unused(18bit)
并发标记: 并发标记是遍历对象图做可达性分析的阶段,前后也要经过类似于G1、Shenandoah的初始标记、最终标记的短暂停顿。ZGC 标记阶段会更新染色指针的 Marked 0、Marked 1 标记位并发预备重分配: 这个阶段需要根据特定的查询条件统计得出本次收集过程要清理哪些 Region,将这些Region组成重分配集(决定了分配集中存活对象会被重新复制到其他的 Region 中,里面的 Region 会释放)并发重分配:重分配集中的存活对象复制到新的Region上,并为重分配集中的每个Region维护一个转发表,记录从旧对象到新对象的转向关系(并发使用内存屏障实现指针 \"自愈\")。并发重映射(Concurrent Remap): 重映射所做的就是修正整个堆中指向重分配集中旧对象的所有引用
Finalizable
Remapped
Markedl
Marked0
初始标记仅仅只是标记一下GC Roots 能关联的对象,速度很快,需要 STW
CMS 收集器是一种以获取最短回收停顿时间为目标的收集器(使用B/S上)CMS 三个缺点:CMS 收集器堆处理器资源非常敏感;由于 CMS 收集器无法处理浮动垃圾(其他线程产生垃圾,当次无法回收的垃圾),有可能会出现 \"Concurrent Mode Failure\" 失败进而导致另一次完全 STW 的 Full GC 产生;空间碎片过多,将会给大对象带来很大麻烦(内存不足);
转发指针:在原有对象布局结构的最前面统一增加一个新的引用字段,在正常不处于并发移动的情况下,该引用指针指向对象自己转发指针加入后旧对象上的转发指针的引用位置,使其指向新的对象,便可将所有对该对象的访问转发到新的副本上转发指针访问的并发问题:Shenandoah 采用 CAS 来保证收集线程和用户线程只有一个能访问转发指针转发指针的执行频率问题:同时设置读、写屏障进行拦截
找出要回收的对象,还要重新整理 SATB(原始快照) 记录下的在并发时有引用变动的对象
并发清理
初始标记:与 G1 一样,首先标记与 GC Roots 之间关联的对象,这个阶段仍是 STW并发标记:与 G1 一样,遍历对象图,标记出全部可达的对象最终标记:与 G1 一样,处理剩余的 SATB 扫描,并在这个阶段统计出回收价值最高的 Region,将这些 Region 构成一组回收集,需要 STW并发清理:这个阶段用于清除那些整个内存连一个存活对象都没有找到的 Region并发回收:把回收集存活的对象先复制一份到其他未被使用的 Region 中,Shenandoash 会通过读屏障和被称为 Brooks Pointers 来解决并发场景复制对象的问题。初始引用更新:引用更新是并发回收阶段复制对象结束后,还需要把堆中所有指向接对象的引用指向修正到复制后的新地址。初始引用更新是建立一个线程集合点,确保所有并发回收阶段中进行的收集器线程都已完全分配给她们的对象移动任务,会产生一个 STW并发引用更新:真正更新引用更新操作,按照内存物理地址的顺序,线性的搜索出引用类型,把旧值改为新值。最终引用更新:解决了堆中的引用更新后,还需要修正存在于 GC Roots 中的引用,需要 STW并发清理:经过并发回收之后和引用更新后,整个回收集中所有的 Region 已为存活对象,再次调用并发清理过程来回收这些 Region 的内存空间
收藏
收藏
0 条评论
下一页