序
Variable Handles
Variable Handles的API主要是用来取代java.util.concurrent.atomic包以及sun.misc.Unsafe类的功能。一个variable handle是一个variable的类型引用,用来在一系列访问模式下来读写variable。支持的variable包括实例变量,静态成员,数据元素等。Variable Handles需要依赖jvm的增强及编译器的协助,即需要依赖java语言规范及jvm规范的升级。
实例
目标类
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) +
'}';
}
}
访问public成员
@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);
}
输出
99
访问proteced成员
@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]}
访问private成员
@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);
}
输出
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);
}
输出
Demo{name='init', count=1, sum=100, data=[100, 300, 7]}
access modes
主要的访问模式有如下几种:
read access modes
such as reading a variable with volatile memory ordering effects;
主要有如下几个方法:get, getVolatile, getAcquire, getOpaque.
get
with memory semantics of reading as if the variable was declared non-{@code volatile}. Commonly referred to as plain read access.
getVolatile
用于读取volatile修饰的变量
getAcquire
ensures that subsequent loads and stores are not reordered before this access.
getOpaque
accessed in program order, but with no assurance of memory ordering effects with respect to other threads.
write access modes
such as updating a variable with release memory ordering effects;
主要有如下几个方法:set, setVolatile, setRelease, setOpaque.
atomic update access modes
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.
numeric atomic update access modes
such as get-and-add with plain memory order effects for writing and acquire memory order effects for reading.
主要有如下几个方法:getAndAdd, getAndAddAcquire, getAndAddRelease
bitwise atomic update access modes
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。
doc