[Java in-depth research] 8. Java's Unsafe class details, in-depth study of unsafe
Java cannot directly access the underlying operating system, but is accessed through local methods. The Unsafe class provides hardware-level atomic operations and mainly provides the following features:
1. memory can be allocated through the Unsafe class and can be released;
Class Three local methods allocateMemory, reallocatemory, and freemory are used to allocate memory, expand memory, and release memory, respectively, corresponding to the three methods in C language.
public native long allocateMemory(long l);public native long reallocateMemory(long l, long l1);public native void freeMemory(long l);
2. You can locate the memory location of a field of the object, or modify the field value of the object, even if it is private;
Field positioning:
In JAVA, the location of object fields may be achieved through the staticFieldOffset method. This method returns the memory address offset of the given field. This value is unique and fixed for the given filed.
The getIntVolatile method obtains the value of the integer field corresponding to the offset address in the object and supports the volatile load syntax.
The getLong method obtains the value of the long field corresponding to the offset address in the object.
Array Element positioning:
The Unsafe class contains many constants ending with BASE_OFFSET, such as ARRAY_INT_BASE_OFFSET and ARRAY_BYTE_BASE_OFFSET. These constant values are obtained through the arrayBaseOffset method. The arrayBaseOffset method is a local method that obtains the offset address of the first element of the array. There are many constants ending with INDEX_SCALE In the Unsafe class, such as ARRAY_INT_INDEX_SCALE and ARRAY_BYTE_INDEX_SCALE. These constant values are obtained through the arrayIndexScale method. The arrayIndexScale method is also a local method to obtain the conversion factor of the array, that is, the incremental address of the elements in the array. Use arrayBaseOffset with arrayIndexScale to locate the position of each element in the array in the memory.
public final class Unsafe { public static final int ARRAY_INT_BASE_OFFSET; public static final int ARRAY_INT_INDEX_SCALE; public native long staticFieldOffset(Field field); public native int getIntVolatile(Object obj, long l); public native long getLong(Object obj, long l); public native int arrayBaseOffset(Class class1); public native int arrayIndexScale(Class class1); static { ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset([I); ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale([I); }}
3. Suspension and recovery
The suspension of a thread is implemented through the park method. After the park method is called, the thread will be blocked until conditions such as timeout or interruption occur. Unpark can terminate a suspended thread and restore it to normal. The suspension of threads in the entire concurrency framework is encapsulated in the LockSupport class. The LockSupport class has various version pack methods, but eventually all call the Unsafe. park () method.
public class LockSupport { public static void unpark(Thread thread) { if (thread != null) unsafe.unpark(thread); } public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(false, 0L); setBlocker(t, null); } public static void parkNanos(Object blocker, long nanos) { if (nanos > 0) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(false, nanos); setBlocker(t, null); } } public static void parkUntil(Object blocker, long deadline) { Thread t = Thread.currentThread(); setBlocker(t, blocker); unsafe.park(true, deadline); setBlocker(t, null); } public static void park() { unsafe.park(false, 0L); } public static void parkNanos(long nanos) { if (nanos > 0) unsafe.park(false, nanos); } public static void parkUntil(long deadline) { unsafe.park(true, deadline); }}
4. CAS operations
Implemented through the compareAndSwapXXX Method
/*** Compare the values in the memory position and the expected values in the obj offset. If the values are the same, update the values. This update is not interrupted. ** @ Param obj: the object to be updated * @ param offset the offset of the integer field in obj * @ param expect CT to have a value in the field * @ param update if the expected values of CT and Current field same value, set the filed value to this new value * @ return. If the field value is changed, true */public native boolean compareAndSwapInt (Object obj, long offset, int exact CT, int update) is returned );
The CAS operation has three operands: memory value M, expected value E, and new value U. If M = E, the memory value is changed to B. Otherwise, nothing is done.