project/jvm/CMS.md

4.1 KiB
Raw Blame History

串行垃圾收集器Serial和Serial Old

并行收集器吞吐量优先Parallel Scanvenge、Parallel Old

并发收集器停顿时间优先CMS、G1

CMS

Concurrent Mark Sweep

老年代

垃圾收集算法:标记清除算法,不使用复制主要是减少时间。

耗时的使用并发标记不耗时的使用并行标记STOP WORLD

  1. 初始标识标记GC Root 直接关联对象不用Tracing速度很快
  2. 并发标识进行GC Root Tracing
    1. 并发预处理年轻代指向老年代一次minor GC后处理
    2. 可终止的预处理,
  3. 重新标识,修改并发标记因用户程序变动的内容
  4. 并发清理,清除不可达对象回收空间,同时有新垃圾产生,留着下次清理称为浮动垃圾

Backgroud CMS

记忆集

跨代收集,用于记录从非收集区域指向收集区域的指针集合的数据结构。

卡表

记忆集是我们针对跨代引用问题提出的思想,而卡表则是针对于该思想的具体实现。

本身就是一个字节数组。

CART_TABLE[]每个元素对应着其标识的内存区域一块特定大小的内存块称为卡页hostspot使用的卡页是2^9大小即512字节。

一个卡页中包含对个对象只要有一个对象字段存在跨代指针其对应的卡表的元素标识就变成1标识该元素变脏否则为0。GC时只要筛选本收集区的卡表中变脏的元素加入GCRoot里。

Foreground CMS

并发失败才会走这种模式

CMS标记压缩算法----MSCMark Sweep Compact

三色标记

通俗讲解标记过程。

黑色:对象已经被垃圾回收扫描过,且所有对象已经被垃圾回收扫描过

灰色:对象已经被垃圾回收扫描过,但这个对象上至少存在一个引用还没有被扫描。

白色:对象未被垃圾收集器访问过。

RSet RemeberSet引用集

处理老年代指向新生代,新生代指向老年代。

两种方式记录引用关系

obj1.方法=obj2

point out 记录obj1所在的Region所对应的Rset记录的是obj2的位置

point in 在obj2所在的Rset记录obj1的位置

cup缓存行128字节

hostsport 卡页 512字节 128*512=64k

写屏障的内存伪共享问题

问题:

如果不同线程对对象引用的更新操作恰好位于同一个63KB区域内这将导致同时更新卡表的同一个缓存行从而造成缓存行的写回、无效化或者同步操作间接影响程序性能。

解决方案:

不采用无条件的写屏障而是先检查卡表标记只有当该卡表项未被标记过才将其标记为dirty这就是JDK7中引入的解决方法引入了一个新的JVM参数-XX:+UseCondCardMark.

  1. 稀疏表
    1. 本质上就是一种Hash表Key是Region的起始地址Value是一个数据里面存储的元素是卡表的索引号。
  2. 粗粒度位图
    1. 当细粒度位图size超过阈值时所有region形成一个bitMap。如果有region对当前Region有指针指向就设置器对应的bit为1也就是粗粒度位图。
  3. 细粒度位图
    1. 就是一个C位图但是这个位图可以详细的记录我们的内存变化包括并发标记修改对应元素标识等
    2. 当稀疏表指定region的card数量超过阈值时则在细粒度位图中创建一个对应的PerRegionTable对象。
    3. 一个Region地址链表维护当前Region中所有card对应的一个BitMap集合。

G1

Garbage-first

  1. 内存空间重新定义
  2. 更短的停顿时间
  3. 某种程度上去解决空间碎片

时间更短,某种程度可以解决空间碎片。

筛选引擎,优先筛选重要的(根据设置时间)。

  1. Empty Space
  2. Eden Space
  3. Survivor Space
  4. Old Generation
  5. Humongous

TLAB

线程本地分配缓冲区Thread Local Allocation Buffer

分配空间时为了提高JVM的运行效率劲量减少临界区范围避免全局锁。G1的通常的应用场景中会存在大量的访问器同时执行为减少锁冲突jvm引入TLAB机制。

垃圾收集器的三种模式

  1. young GC
  2. mixed GC

pss队列

ZGC

Z Garbage Collector