写屏障是jvm在对象引用赋值时自动插入的底层机制,负责更新卡表以加速minor gc跨代扫描,并通过satb策略捕获引用断开动作防止并发标记漏标,属gc收集器内置硬逻辑,不可由java代码控制。

写屏障是 JVM 在对象引用赋值时自动插入的底层机制,不是 Java 代码能直接调用或控制的,它像一个隐形守门人,卡在每次 obj.field = newObj 这类操作之后,默默完成两件关键事:更新卡表、保障并发标记不漏标。
写屏障怎么让 Minor GC 不用扫全堆
新生代回收(Minor GC)必须知道老年代有没有对象正引用着新生代里的对象。但挨个检查整个老年代太慢。于是 JVM 把老年代切成 512 字节一块的“卡页”,对应一张字节数组——卡表。只要某块卡页里有跨代引用(比如老年代对象 A 指向了新生代对象 B),写屏障就会把这张卡对应的表项标为 dirty(脏卡)。
- 每次发生跨代写操作(如老年代对象修改字段指向新生代),写屏障立即触发 mark card 动作
- Minor GC 时只扫描所有 dirty 卡页内的对象,跳过干净区域,效率大幅提升
- 加参数
-XX:+UseCondCardMark可避免重复标记同一张卡,缓解多核下缓存行伪共享问题
写屏障怎么防止并发标记漏标
G1 用 SATB(初始快照)策略做并发标记。它不关心新引用,专抓“断开的旧引用”——比如一个灰色对象刚把对白色对象的引用删掉,这个白色对象就可能被漏标、误回收。写屏障在此刻捕获这个删除动作,把原引用对象(被删掉的那个白色对象)记录下来,留待后续重新标记阶段处理。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不是记录“谁指向谁”,而是记录“谁被谁断开了”
- 这种补偿机制和三色标记配合:黑色对象不直接连白色对象,灰色对象变动时由写屏障兜底
- CMS 则用增量更新思路,写屏障记录新增引用;G1 选 SATB,更适合大堆与混合回收场景
写屏障不是功能开关,而是编译期植入的硬逻辑
无论代码是解释执行还是 JIT 编译后的机器码,JVM 都会在生成指令时,把写屏障逻辑(比如更新卡表 + SATB 日志写入)直接塞进赋值操作之后。你写的 a.b = c,实际运行的是“赋值 + 卡表检查 + 引用快照记录”这一整套原子动作。
- 没有单独的 API 或注解可以开启/关闭写屏障,它是收集器(G1/CMS)的内置能力
- 它带来轻微性能开销,但远小于全堆扫描或 STW 延长的代价
- 高并发下要注意伪共享:多个线程频繁修改不同对象却命中同一缓存行,导致卡表更新互相阻塞
理解写屏障,关键是抓住它“被动触发、双轨并行”的特性——一边帮 GC 快速定位跨代引用,一边给并发标记兜住漏标风险。它不出现在 Java 层,却深刻影响着吞吐、延迟与内存安全。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










