VarHandle 是 Java 9 引入的、JVM 深度支持的类型化变量操作机制,用于安全替代已弃用且受限的 sun.misc.Unsafe。

VarHandle 是 Java 9 正式引入的、用于安全替代 sun.misc.Unsafe 的标准化变量操作机制,不是语法糖,也不是 AtomicXXX 类的简化版,而是 JVM 层面深度支持的类型化访问抽象。
为什么必须用 VarHandle 替代 Unsafe
Unsafe 在 JDK 9 起已被标记为 @Deprecated,JDK 17 默认禁止反射访问其单例实例——调用 Unsafe.getUnsafe() 可能成功,但后续执行 compareAndSwapInt 等操作会直接抛出 InaccessibleObjectException。这是因为模块系统在启动时就拦截了对非导出内部 API 的反射调用。
- Unsafe 依赖运行时计算字段偏移量,不同 JVM 实现或 GC 算法下 offset 可能变化;VarHandle 将偏移抽象为句柄,由 JVM 内部保证一致性
- Unsafe 的方法参数顺序易错(如
compareAndSwapInt(obj, offset, expect, update)),且无类型约束;VarHandle 的compareAndSet(obj, expected, newValue)在编译期即校验类型 - Unsafe 绕过所有访问控制和安全管理器,存在崩溃、内存污染、跨平台错位等高风险;VarHandle 全程走标准 API 流程,权限失败时明确抛出
IllegalAccessException或NoSuchFieldException
如何正确创建 VarHandle 实例
创建方式取决于字段访问级别和目标类型,核心是获取有权限的 MethodHandles.Lookup,再调用对应查找方法:
- 访问 public 或 protected 实例字段:
MethodHandles.lookup().in(Owner.class).findVarHandle(Owner.class, "fieldName", type) - 访问 private 实例字段:必须用
MethodHandles.privateLookupIn(Owner.class, MethodHandles.lookup())获取专用 lookup,再调用findVarHandle - 访问静态字段:
lookup.findStaticVarHandle(Owner.class, "fieldName", type) - 访问数组元素:
MethodHandles.arrayElementVarHandle(int[].class),无需反射,直接传入数组类
注意:字段类型必须与声明类型严格一致(int.class 对应 int 字段,不能是 Integer);final 字段仅支持 get,不可用于 compareAndSet 或 set。
VarHandle 的关键访问模式
VarHandle 提供细粒度的内存语义控制,每种模式对应不同强度的内存屏障:
-
普通读写(
get/set):无内存屏障,适用于单线程或已同步场景 -
Opaque 模式(
getOpaque/setOpaque):最弱可见性保证,仅确保当前线程看到最新值,不禁止重排序,性能开销最小 -
Acquire/Release 模式(
getAcquire/setRelease):构建获取/释放语义,常用于自定义锁或非阻塞算法中控制临界区边界 -
Volatile 模式(
getVolatile/setVolatile):等效于传统 volatile 变量,提供完全内存屏障和 happens-before 保证,适合共享状态标志位 -
原子更新模式(
compareAndSet、getAndAdd、getAndBitwiseAnd等):支持 CAS 和各种原子运算,类型安全且无需偏移量
使用注意事项与最佳实践
VarHandle 实例必须缓存复用,不能每次操作都重新创建——查找过程涉及权限检查和字段绑定,开销较大。
- 实例字段句柄操作时,必须传入具体对象实例(
HANDLE.get(obj)) - 静态字段句柄操作时,第一个参数传
null(HANDLE.get(null)) - 数组句柄的
get/set方法第二个参数是索引(arrayHandle.get(array, index)),不是字节偏移量 - 泛型字段(如
List)的 VarHandle 类型仍是field VarHandle,但get/set方法签名按类型擦除后处理(即Object) - 不要试图用
findVarHandle访问其他模块的 private 字段——除非显式开放了模块导出和开放权限
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











