本文主要研究下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