CAS机制演进体现为Unsafe类中compareAndSwapXXX方法在调用路径、安全管控与JIT优化上的持续收敛:从JDK 8的sun.misc.Unsafe公开使用,到JDK 9模块化迁移至jdk.internal.misc.Unsafe并强化访问限制,再到JDK 10起通过@HotSpotIntrinsicCandidate注解实现JIT内联优化,最终在Java 17+后由VarHandle和Critical NIO提供标准化替代方案,Unsafe CAS方法已标记为@Deprecated(forRemoval = true)。

CAS 机制在 JDK 内部的演进,核心体现在 Unsafe 类中 compareAndSwapXXX 系列方法的设计逻辑、调用路径与安全管控变化上,而非简单“新增或废弃 API”。它不是线性迭代的版本升级,而是随 JVM 实现、JDK 模块化和安全策略逐步收敛的过程。
Unsafe 的 CAS 方法始终基于硬件指令,但入口不断收窄
JDK 早期(如 JDK 8)中,Unsafe 提供了 compareAndSwapInt、compareAndSwapLong、compareAndSwapObject 等公开方法,直接暴露给 java.util.concurrent.atomic 包内原子类使用。这些方法底层统一委托给 JVM 的 Atomic::cmpxchg(x86 平台对应 lock cmpxchg 指令),由 C++ 实现并内联汇编保障原子性。
- 它们从不面向应用开发者开放——
Unsafe.getUnsafe()会校验调用类是否由系统类加载器加载,否则抛出SecurityException - 所有原子类(如
AtomicInteger)都通过静态字段缓存Unsafe实例,并用objectFieldOffset定位字段内存偏移,构成“字段 + 偏移 + 预期值 + 新值”的标准调用范式 - 没有新增“新 CAS 方法”,只有更严格的封装:JDK 9 引入模块系统后,
jdk.internal.misc.Unsafe被划入jdk.unsupported模块,禁止跨模块反射访问
从 sun.misc.Unsafe 到 jdk.internal.misc.Unsafe 的包路径迁移
JDK 1.8 使用 sun.misc.Unsafe;JDK 9 开始正式迁移到 jdk.internal.misc.Unsafe,这是模块化强制要求的结果。包名变更本身不改变 CAS 行为,但带来两层实质影响:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 编译期拦截:非
java.base模块无法声明对jdk.unsupported的依赖,javac直接报错 - 运行时限制:即使通过反射绕过编译检查,JVM 在启动时可通过
--illegal-access=deny彻底禁用Unsafe访问 - 方法签名保持完全兼容,比如
compareAndSwapInt(Object, long, int, int)参数顺序与语义未变
@HotSpotIntrinsicCandidate 注解推动 JIT 优化落地
自 JDK 10 起,Unsafe 中关键 CAS 方法被标注 @HotSpotIntrinsicCandidate,标志着 HotSpot JVM 将其识别为可内联替换的热点操作。这不是新增方法,而是让 JIT 编译器在运行时把 Java 层调用直接替换为 CPU 原生指令:
立即学习“Java免费学习笔记(深入)”;
- 例如
AtomicInteger.getAndIncrement()在热点代码中不再走 JNI 进入 C++ 层,而由 JIT 生成紧凑的lock xadd序列 - 这种优化对开发者透明,但大幅降低 CAS 的实际开销,使自旋重试更可持续
- 该注解仅对 HotSpot 有效,其他 JVM 实现(如 OpenJ9)需自行适配对应 intrinsic 机制
Java 17+ 后,CAS 能力转向 VarHandle 和 Critical NIO
官方明确鼓励迁移:JDK 9 引入 java.lang.invoke.VarHandle,JDK 14 加入 java.lang.foreign.MemorySegment(后演进为 MemoryAddress),它们提供标准化、安全可控的底层内存访问能力:
-
VarHandle.compareAndSet()接口统一,支持字段、数组、堆外内存,且可通过MethodHandles.privateLookupIn控制访问权限 -
ByteBuffer.compareAndExchangeXXX()(JDK 21 引入)将 CAS 扩展到堆外缓冲区场景,替代手工调用Unsafe -
Unsafe的 CAS 方法并未删除,但已标记为@Deprecated(forRemoval = true)(JEP 442 提案),未来版本可能移除

















