“VarHandle” VarHandle 的出现替代了java.util.concurrent.atomic和sun.misc.Unsafe的部分操作。并且提供了一系列标准的内存屏障操作,用于更加细粒度的控制内存排序。在安全性、可用性、性能上都要优于现有的API。VarHandle 可以与任何字段、数组元素或静态变量关联,支持在不同访问模型下对这些类型变量的访问,包括简单的 read/write 访问,volatile 类型的 read/write 访问,和 CAS(compare-and-swap)等。
Unsafe 是不建议开发者直接使用的,因为 Unsafe 所操作的并不属于Java标准,会容易带来一些安全性的问题。JDK9 之后,官方推荐使用 java.lang.invoke.Varhandle 来替代 Unsafe 大部分功能,对比 Unsafe ,Varhandle 有着相似的功能,但会更加安全,并且,在并发方面也提高了不少性能。
Varhandle是对变量或参数定义的变量系列的动态强类型引用,包括静态字段,非静态字段,数组元素或堆外数据结构的组件。 在各种访问模式下都支持访问这些变量,包括简单的读/写访问,volatile 的读/写访问以及 CAS (compare-and-set)访问。简单来说 Variable 就是对这些变量进行绑定,通过 Varhandle 直接对这些变量进行操作。
import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.util.Arrays; public class VarHandleX { public int publicVar = 1; protected int protectedVar = 2; @SuppressWarnings("FieldMayBeFinal") private int privateVar = 3; public int[] arrayData = new int[]{1, 2, 3}; @Override public String toString() { return "VarHandleX{" + "publicVar=" + publicVar + ", protectedVar=" + protectedVar + ", privateVar=" + privateVar + ", arrayData=" + Arrays.toString(arrayData) + '}'; } public static void main(String[] args) { try { VarHandleX instance = new VarHandleX(); VarHandle varHandle = MethodHandles.privateLookupIn(VarHandleX.class, MethodHandles.lookup()) .findVarHandle(VarHandleX.class, "privateVar", int.class); varHandle.set(instance, 33); System.out.println(instance); protectedDemo(); protectedDemo2(); publicDemo(); arrayDemo(); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } private static void protectedDemo() throws NoSuchFieldException, IllegalAccessException { VarHandleX instance = new VarHandleX(); VarHandle varHandle = MethodHandles.privateLookupIn(VarHandleX.class, MethodHandles.lookup()) .findVarHandle(VarHandleX.class, "protectedVar", int.class); varHandle.set(instance, 22); System.out.println("protected: " + instance); } private static void protectedDemo2() throws NoSuchFieldException, IllegalAccessException { VarHandleX instance = new VarHandleX(); VarHandle varHandle = MethodHandles.lookup() .in(VarHandleX.class) .findVarHandle(VarHandleX.class, "protectedVar", int.class); varHandle.set(instance, 22); System.out.println("protected 2: " + instance); } private static void publicDemo() throws NoSuchFieldException, IllegalAccessException { VarHandleX instance = new VarHandleX(); VarHandle varHandle = MethodHandles.lookup() .in(VarHandleX.class) .findVarHandle(VarHandleX.class, "publicVar", int.class); varHandle.set(instance, 11); System.out.println("public: " + instance); } private static void arrayDemo() throws NoSuchFieldException, IllegalAccessException { VarHandleX instance = new VarHandleX(); VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class); arrayVarHandle.compareAndSet(instance.arrayData, 0, 1, 11); arrayVarHandle.compareAndSet(instance.arrayData, 1, 2, 22); arrayVarHandle.compareAndSet(instance.arrayData, 2, 3, 33); System.out.println("array: " + instance); } } 获取Varhandle方式汇总 MethodHandles.privateLookupIn(class, MethodHandles.lookup())获取访问私有变量的Lookup MethodHandles.lookup() 获取访问protected、public的Lookup findVarHandle: 用于创建对象中非静态字段的VarHandle。接收参数有三个,第一个为接收者的class对象,第二个是字段名称,第三个是字段类型。 findStaticVarHandle: 用于创建对象中静态字段的VarHandle,接收参数与findVarHandle一致。 unreflectVarHandle: 通过反射字段Field创建VarHandle。 MethodHandles.arrayElementVarHandle(int[].class) 获取管理数组的 Varhandle 功能 VarHandle来使用plain、opaque、release/acquire和volatile四种共享内存的访问模式,根据这四种共享内存的访问模式又分为写入访问模式、读取访问模式、原子更新访问模式、数值更新访问模式、按位原子更新访问模式。
...