Unsafe array methods
Unsafe has a group of array methods and fields. They are used to locate array element and do memory model related operations like atomic cas or lazy store putOrderedInt etc.
For example, the assignment arr[i] = arr[i] + 3
is not atomic with 3 ops: load, add and store.
With usnafe, if we know the offset of ith element, we can call unsafe.compareAndSwapInt(arr, ithOffset, original, new)
to do atomic update.
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class UnsafeArrayTest {
public static void main(String[] args) throws Exception {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
// base and offset are also stored as public static fields of Unsafe
int base = unsafe.arrayBaseOffset(int[].class);
int scale = unsafe.arrayIndexScale(int[].class);
System.out.println(base + " " + scale); // 16 4
int[] arr = new int[5];
// offset of arr[2]
long offset = (long)base + scale * 2;
unsafe.putInt(arr, offset, 10); // arr[2] = 10
System.out.println(arr[2]); // 10
unsafe.compareAndSwapInt(arr, offset, 10, 13); // cas arr[2]
System.out.println(arr[2]); // 13
}
}
Above sample code defines an int array and update the 2th element to 10 first and 13 later. We can reason that array offset is 16 bytes from the insight of object layout: object mark words takes 8 bytes, 4 bytes pointer points to the array class, remaining 4 bytes is the array length. Int type is 4 bytes so the scale is 4. Since JVM will be different in different hardware architectures, it’s safe to call unsafe method to determine array offset and element scale.
Above is a code snippet from ForkJoinPool.java. ASHIFT is the shift of multiplication. If multiply 4, left shifts 2. If multiple 8, left shifts 3. So the array element located at base + i * scale
can be expressed by base + (i << ASHIFT)
. Bit operation is faster than multiplication. It's a common way to manipulate array with Unsafe in JDK concurrent package.