简介

现代JVM,堆空间通常被划分为新生代和老年代。由于新生代的垃圾收集通常很频繁,如果老年代对象引用了新生代的对象,那么,需要跟踪从老年代到新生代的所有引用,从而避免每次YGC时扫描整个老年代,减少开销。

对于HotSpot JVM,使用了卡标记(Card Marking)技术来解决老年代到新生代的引用问题。具体是,使用卡表(Card Table)和写屏障(Write Barrier)来进行标记并加快对GC Roots的扫描。

卡表(Card Table)

基于卡表(Card Table)的设计,通常将堆空间划分为一系列2次幂大小的卡页(Card Page)。

卡表(Card Table),用于标记卡页的状态,每个卡表项对应一个卡页。

HotSpot JVM的卡页(Card Page)大小为512字节,卡表(Card Table)被实现为一个简单的字节数组,即卡表的每个标记项为1个字节。

当对一个对象引用进行写操作时(对象引用改变),写屏障逻辑将会标记对象所在的卡页为dirty。

OpenJDK/Oracle 1.6/1.7/1.8 JVM默认的卡标记简化逻辑如下:

CARD_TABLE [this address >> 9] = 0;

首先,计算对象引用所在卡页的卡表索引号。将地址右移9位,相当于用地址除以512(2的9次方)。可以这么理解,假设卡表卡页的起始地址为0,那么卡表项0、1、2对应的卡页起始地址分别为0、512、1024(卡表项索引号乘以卡页512字节)。

其次,通过卡表索引号,设置对应卡标识为dirty。

带来的2个问题

1.无条件写屏障带来的性能开销

每次对引用的更新,无论是否更新了老年代对新生代对象的引用,都会进行一次写屏障操作。显然,这会增加一些额外的开销。但是,与YGC时扫描整个老年代相比较,这个开销就低得多了。

不过,在高并发环境下,写屏障又带来了虚共享(false sharing)问题。

2.高并发下虚共享带来的性能开销

在高并发情况下,频繁的写屏障很容易发生虚共享(false sharing),从而带来性能开销。

假设CPU缓存行大小为64字节,由于一个卡表项占1个字节,这意味着,64个卡表项将共享同一个缓存行。

HotSpot每个卡页为512字节,那么一个缓存行将对应64个卡页一共64*512=32KB。

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

一个简单的解决方案,就是不采用无条件的写屏障,而是先检查卡表标记,只有当该卡表项未被标记过才将其标记为dirty。

这就是JDK 7中引入的解决方法,引入了一个新的JVM参数-XX:+UseCondCardMark,在执行写屏障之前,先简单的做一下判断。如果卡页已被标识过,则不再进行标识。

简单理解如下:

if (CARD_TABLE [this address >> 9] != 0)
CARD_TABLE [this address >> 9] = 0;

与原来的实现相比,只是简单的增加了一个判断操作。

虽然开启-XX:+UseCondCardMark之后多了一些判断开销,但是却可以避免在高并发情况下可能发生的并发写卡表问题。通过减少并发写操作,进而避免出现虚共享问题(false sharing)。

也用于CMS GC

CMS在并发标记阶段,应用线程和GC线程是并发执行的,因此可能产生新的对象或对象关系发生变化,例如:

  • 新生代的对象晋升到老年代;
  • 直接在老年代分配对象;
  • 老年代对象的引用关系发生变更;
  • 等等。

对于这些对象,需要重新标记以防止被遗漏。为了提高重新标记的效率,并发标记阶段会把这些发生变化的对象所在的Card标识为Dirty,这样后续阶段就只需要扫描这些Dirty Card的对象,从而避免扫描整个老年代。

参考:

jvm的card table数据结构

JVM之卡表(Card Table)

JVM调优:CardTable简介

JVM-卡表(Card Table)的更多相关文章

  1. mysql 命令重命名表RENAME TABLE 句法

    mysql 命令重命名表RENAME TABLE 句法 RENAME TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2,...]更 ...

  2. Openvswitch原理与代码分析(5): 内核中的流表flow table操作

      当一个数据包到达网卡的时候,首先要经过内核Openvswitch.ko,流表Flow Table在内核中有一份,通过key查找内核中的flow table,即可以得到action,然后执行acti ...

  3. Lua中的weak表——weak table

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  4. ABAP内表(internal table)有关的系统变量

    SY-TABIX – 内表当前行的索引号.SY-TABIX 的值可以被以下命令修改,但是只适用于索引表(index table).对于哈希表(Hashed table),这个系统变量的值为空或0. A ...

  5. Lua中的weak表——weak table(转)

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  6. Oracle使用Sql把XML解析成表(Table)的方法

    SELECT * FROM XMLTABLE('$B/DEAL_BASIC/USER_DEAL_INFO' PASSING XMLTYPE('<?xml version="1.0&qu ...

  7. 表(Table)

    虽然我们已经将不同用途的物品保存在不同的仓库中了,但是在同一个仓库中数据的保存仍然存在问题.比如食品分为熟食.生肉.大米等,如果把他们随意的堆放在一起,就会造成我们无法很容易的对这些食品进行管理,当要 ...

  8. Lua表(table)的用法_个人总结

    Lua表(table)的用法_个人总结 1.表的创建及表的介绍 --table 是lua的一种数据结构用来帮助我们创建不同的数据类型.如:数组和字典--lua table 使用关联型数组,你可以用任意 ...

  9. 算法与数据结构基础 - 哈希表(Hash Table)

    Hash Table基础 哈希表(Hash Table)是常用的数据结构,其运用哈希函数(hash function)实现映射,内部使用开放定址.拉链法等方式解决哈希冲突,使得读写时间复杂度平均为O( ...

随机推荐

  1. Ubuntu16.04下安装Cmake-3.8.2并为其配置环境变量

    下载安装包 首先我们到官网下载最新的cmake二进制安装包https://cmake.org/files/ 这里,我下载的是比较新的cmake-3.8.2-Linux-x86_64.tar.gz解压安 ...

  2. Mondb

    1. MongoDB简介 • MongoDB是为快速开发互联网Web应用而设计的数据库系统.• MongoDB的设计目标是极简.灵活.作为Web应用栈的一部分.• MongoDB的数据模型是面向文档的 ...

  3. Java List<T> 去重

    1.List<T>,是个泛型,实际业务里,它经常是一个bean,例如Person类,里面有age.name等属性. 2.如果List<Person>  ps 有重复的数据,我们 ...

  4. ES6-Symbol.iterator 迭代器

    一个数据结构只要部署了Symbol.iterator属性就能使用 for...of遍历 与 ...运算符 操作 Object身上没有Symbol.iterator,当直接使用时会报错 let obj ...

  5. TreeMap 原理

    基于jdk1.8 TreeMap第一个想到的就是有序,当然也不是线程安全 TreeMap实现NavigableMap接口,说明支持一系列的导航方法 一.构造方法 public TreeMap() { ...

  6. what is variable?

    what is variable? variable:pytorch中的变量,存储tensor,数值会不断变动 在 Torch 中的 Variable 就是一个存放会变化的值的地理位置. 里面的值会不 ...

  7. 【shell脚本】检查内存使用情况===chenkMen.sh

    检查内存使用情况,当内存可使用等于100时,释放缓存 [root@localhost thy]# cat checkMem.sh #!/bin/bash #防止内存溢出问题 used=`free -m ...

  8. vue 移动端禁止浏览器后退,禁止安卓和ios点击后退操作乱跳页面

    开发微信公众号网页,页面登录成功之后,是禁止再次返回到登录页. 我在页面设置了让禁止跳到登录页,可是在手机上有自带的微信浏览器后退按钮,所以必须要禁止浏览器后退,才能禁止后退到登录页. 刚开始百度,查 ...

  9. CompletableFuture2

    public class CompletableFuture2 { public static void main(String[] args) throws InterruptedException ...

  10. OpenGL入门1.4:纹理/贴图Texture

    每一个小步骤的源码都放在了Github 的内容为插入注释,可以先跳过 前言 游戏玩家对Texture这个词应该不陌生,我们已经知道了怎么为每个顶点添加颜色来增加图形的细节,但,如果想让图形看起来更真实 ...