本文主要研究下JEP 193: Variable Handleshtml
Variable Handles的API主要是用来取代java.util.concurrent.atomic包以及sun.misc.Unsafe类的功能。一个variable handle是一个variable的类型引用,用来在一系列访问模式下来读写variable。支持的variable包括实例变量,静态成员,数据元素等。Variable Handles须要依赖jvm的加强及编译器的协助,即须要依赖java语言规范及jvm规范的升级。java
public static class Demo { public int count = 1; protected long sum = 100; private String name = "init"; public int[] arrayData = new int[]{3,5,7}; @Override public String toString() { return "Demo{" + "name='" + name + '\'' + ", count=" + count + ", sum=" + sum + ", data=" + Arrays.toString(arrayData) + '}'; } }
@Test public void testSetPublicField() throws NoSuchFieldException, IllegalAccessException { Demo instance = new Demo(); VarHandle countHandle = MethodHandles.lookup() .in(Demo.class) .findVarHandle(Demo.class, "count", int.class); countHandle.set(instance,99); System.out.println(instance.count); }
输出api
99
@Test public void testSetProtectedField() throws NoSuchFieldException, IllegalAccessException { Demo instance = new Demo(); VarHandle countHandle = MethodHandles.lookup() .in(Demo.class) .findVarHandle(Demo.class, "sum", long.class); countHandle.set(instance,99999); System.out.println(instance); }
输出数组
Demo{name='init', count=1, sum=99999, data=[3, 5, 7]}
@Test public void testSetPrivateField() throws NoSuchFieldException, IllegalAccessException { Demo instance = new Demo(); VarHandle countHandle = MethodHandles.privateLookupIn(Demo.class,MethodHandles.lookup()) .findVarHandle(Demo.class, "name", String.class); countHandle.set(instance,"hello world"); System.out.println(instance); }
输出oracle
Demo{name='hello world', count=1, sum=100, data=[3, 5, 7]}
@Test public void testSetArray(){ Demo instance = new Demo(); VarHandle arrayVarHandle = MethodHandles.arrayElementVarHandle(int[].class); arrayVarHandle.compareAndSet(instance.arrayData,0,3,100); arrayVarHandle.compareAndSet(instance.arrayData,1,5,300); System.out.println(instance); }
输出jvm
Demo{name='init', count=1, sum=100, data=[100, 300, 7]}
主要的访问模式有以下几种:ide
such as reading a variable with volatile memory ordering effects;
主要有以下几个方法:get, getVolatile, getAcquire, getOpaque.
with memory semantics of reading as if the variable was declared non-{@code volatile}. Commonly referred to as plain read access.
用于读取volatile修饰的变量
ensures that subsequent loads and stores are not reordered before this access.
accessed in program order, but with no assurance of memory ordering effects with respect to other threads.
such as updating a variable with release memory ordering effects;
主要有以下几个方法:set, setVolatile, setRelease, setOpaque.
such as a compare-and-set on a variable with volatile memory order effects for both read and writing;
主要有以下几个方法:compareAndSet, weakCompareAndSetPlain, weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetRelease, compareAndExchangeAcquire, compareAndExchange, compareAndExchangeRelease, getAndSet, getAndSetAcquire, getAndSetRelease.
such as get-and-add with plain memory order effects for writing and acquire memory order effects for reading.
主要有以下几个方法:getAndAdd, getAndAddAcquire, getAndAddRelease
such as get-and-bitwise-and with release memory order effects for writing and plain memory order effects for reading.
主要有以下几个方法:getAndBitwiseOr, getAndBitwiseOrAcquire, getAndBitwiseOrRelease, getAndBitwiseAnd, getAndBitwiseAndAcquire, getAndBitwiseAndRelease, getAndBitwiseXor, getAndBitwiseXorAcquire, getAndBitwiseXorRelease.
java9废弃了sun.misc.Unsafe类,引入了VarHandle做为替代。关于access modes部分涉及了JVM的内存模型,须要了解内存可见性、指令重排序等,才能使用好相关api。ui