Detailed explanation of the Unsafe source code of the AQS framework, aqsunsafe

Source: Internet
Author: User

Detailed explanation of the Unsafe source code of the AQS framework, aqsunsafe

Preface

BeforeLockSupportThis article describes the thread blocking tool class, which is implemented by Unsafe at the underlying layer, that is, the park () and unpark () methods, get the pointer offset, and manipulate the memory. This article mainly introduces the Unsafe source code to see what the underlying layer has done.

 

UnsafeSummary

  • Function: Unsafe is a latter type, which encapsulates pointer-like operations and provides some underlying operations that can directly control memory and threads.
  • Use: Unsafe is widely used in nio packages and concurrent packages by JDK, but it is not recommended to be used in the production environment, which is highly risky.
  • Insecure: Uneasiness all refers to the unsafe pointer operations (the pointer is removed only in Java). If the pointer refers to the wrong position or the pointer offset is calculated incorrectly, the result is unimaginable, for example, if someone else's memory is covered, GG Smecta may be involved...
  • Supplement 1: If I have the opportunity to activate JVM, I will re-parse the implementation of some important Unsafe methods from the perspective of JVM source code.
  • Supplement 2: This is a summary of the AQS framework (in stock ).

 

UnsafeData Structure

1. Class Definition

public final class Unsafe

2. Constructor

// Private constructor -- Singleton mode private Unsafe (){}

3. Important Variables

Private static final Unsafe theUnsafe; public static final int INVALID_FIELD_OFFSET =-1; public static final int values; public static final int ARRAY_SHORT_BASE_OFFSET; public static final int ARRAY_CHAR_BASE_OFFSET; public static final int ARRAY_INT_BASE_OFFSET; public static final int ARRAY_LONG_BASE_OFFSET; public static final int values; public static final int ARRAY_OBJECT_BASE_OFFSET; public static final int values; public static final int partition; public static final int ARRAY_CHAR_INDEX_SCALE; public static final int ARRAY_INT_INDEX_SCALE; public static final int ARRAY_LONG_INDEX_SCALE; public static final int partition; public static final int ARRAY_DOUBLE_INDEX_SCALE; public static final int ARRAY_OBJECT_INDEX_SCALE; public static final int ADDRESS_SIZE; private static native void registerNatives (); static {registerNatives (); Reflection. registerMethodsToFilter (Unsafe. class, new String [] {"getUnsafe"}); theUnsafe = new Unsafe (); // Singleton mode-ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe. arrayBaseOffset (boolean []. class); ARRAY_BYTE_BASE_OFFSET = theUnsafe. arrayBaseOffset (byte []. class); ARRAY_SHORT_BASE_OFFSET = theUnsafe. arrayBaseOffset (short []. class); ARRAY_CHAR_BASE_OFFSET = theUnsafe. arrayBaseOffset (char []. class); ARRAY_INT_BASE_OFFSET = theUnsafe. arrayBaseOffset (int []. class); ARRAY_LONG_BASE_OFFSET = theUnsafe. arrayBaseOffset (long []. class); ARRAY_FLOAT_BASE_OFFSET = theUnsafe. arrayBaseOffset (float []. class); ARRAY_DOUBLE_BASE_OFFSET = theUnsafe. arrayBaseOffset (double []. class); ARRAY_OBJECT_BASE_OFFSET = theUnsafe. arrayBaseOffset (Object []. class); ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe. arrayIndexScale (boolean []. class); ARRAY_BYTE_INDEX_SCALE = theUnsafe. arrayIndexScale (byte []. class); ARRAY_SHORT_INDEX_SCALE = theUnsafe. arrayIndexScale (short []. class); ARRAY_CHAR_INDEX_SCALE = theUnsafe. arrayIndexScale (char []. class); ARRAY_INT_INDEX_SCALE = theUnsafe. arrayIndexScale (int []. class); ARRAY_LONG_INDEX_SCALE = theUnsafe. arrayIndexScale (long []. class); ARRAY_FLOAT_INDEX_SCALE = theUnsafe. arrayIndexScale (float []. class); ARRAY_DOUBLE_INDEX_SCALE = theUnsafe. arrayIndexScale (double []. class); ARRAY_OBJECT_INDEX_SCALE = theUnsafe. arrayIndexScale (Object []. class); ADDRESS_SIZE = theUnsafe. addressSize ();}

4. Important Methods

// Get the int value of the given Object memory offset public native int getInt (Object var1, long var2); // set the int value of the given Object memory offset public native void putInt (Object var1, long var2, int var4); public native Object getObject (Object var1, long var2); public native void putObject (Object var1, long var2, Object var4 );//.... get \ set of Boolean, Byte, Char, Short, Long, Float, and Double .... // memory allocation, release // allocate memory public native long allocateMemory (long var1); // expand the memory public n Ative long reallocateMemory (long var1, long var3); public native void setMemory (Object var1, long var2, long var4, byte var6); public void setMemory (long var1, long var3, byte var5) {this. setMemory (Object) null, var1, var3, var5);} // copy the memory public native void copyMemory (Object var1, long var2, Object var4, long var5, long var7 ); public void copyMemory (long var1, long var3, long var5) {this. copyMemory (( Object) null, var1, (Object) null, var3, var5);} // release the memory public native void freeMemory (long var1 ); // get the memory offset of the Field in the Object public native long staticFieldOffset (Field var1); public native long objectFieldOffset (Field var1); public native Object staticFieldBase (Field var1 ); public native void ensureClassInitialized (Class <?> Var1 ); // array element positioning // arrayBaseOffset and arrayIndexScale can be used together to locate the position of each element in the array in the memory // get the offset address of the first element of the array public native int arrayBaseOffset (Class <?> Var1); // obtain the conversion factor of the array, that is, the incremental address of the element in the array public native int arrayIndexScale (Class <?> Var1); public native int addressSize (); public native int pageSize (); // Class definition public native Class <?> DefineClass (String var1, byte [] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6); public native Class <?> DefineClass (String var1, byte [] var2, int var3, int var4); public native Class <?> DefineAnonymousClass (Class <?> Var1, byte [] var2, Object [] var3); // create an instance public native Object allocateInstance (Class <?> Var1) throws InstantiationException; // the Synchronized synchronous block command implements all of the 1.8 versions: @ Deprecatedpublic native void monitorEnter (Object var1); public native void monitorExit (Object var1 ); public native boolean tryMonitorEnter (Object var1); // throw public native void throwException (Throwable var1 ); // CAS operation/*** compares the value in the memory position of the obj offset with the expected value. If the value is the same, it is updated, this update is an uninterrupted * @ param obj object to be updated * @ param offset the offset of the integer field in obj * @ param expect CT wants fi The value in eld * @ param update. If the expected value is the same as the current value of field, set the filed value to this new value * @ return. If the field value is changed, true */public final native boolean compareAndSwapObject (Object obj, long offset, Object exact CT, Object update) is returned ); public final native boolean compareAndSwapInt (Object var1, long var2, int var4, int var5); public final native boolean compareAndSwapLong (Object var1, long var2, long var4, long var6 ); // obtain the specified type value of a given object. vola is supported. Tile load semantics public native Object getObjectVolatile (Object var1, long var2); public native void putObjectVolatile (Object var1, long var2, Object var4); public native int getIntVolatile (Object var1, long var2); // sets the int value of the given Object. It supports the volatile load syntax public native void putIntVolatile (Object var1, long var2, int var4 );//.... there are also volatile get \ put levels of Boolean, Byte, Char, Short, Long, Float, and Double .... public native void putDo UbleVolatile (Object var1, long var2, double var4); public native void putOrderedObject (Object var1, long var2, Object var4); public native void putOrderedInt (Object var1, long var2, int var4); public native void putOrderedLong (Object var1, long var2, long var4 ); // LockSupport class primitive support-suspend and wake up a thread public native void unpark (Object var1); public native void park (boolean var1, long var2); public native int getLoa DAverage (double [] var1, int var2); // provides thread-safe add and set operations for public final int getAndAddInt (Object var1, long var2, int var4) {int var5; do {var5 = this. getIntVolatile (var1, var2);} while (! This. compareAndSwapInt (var1, var2, var5, var5 + var4); return var5;} public final int getAndSetInt (Object var1, long var2, int var4) {int var5; do {var5 = this. getIntVolatile (var1, var2);} while (! This. compareAndSwapInt (var1, var2, var5, var4); return var5 ;}//... there are also Long and Object thread-safe add and set operations... // The fence supports public native void loadFence (); public native void storeFence (); public native void fullFence ();

5. Disabled factory Method

@ CallerSensitivepublic static Unsafe getUnsafe () {Class var0 = Reflection. getCallerClass (); // This method is used to determine whether the caller's class loader is the system core loader (that is, the Bootstrap loader) if (! VM. isSystemDomainLoader (var0.getClassLoader () {throw new SecurityException ("Unsafe") ;}else {return theUnsafe ;}}
  • Let's call the factory method explicitly to view the call result.
Package concurrent; import sun. misc. unsafe; public class UnsafeDemo {public static void main (String [] args) {Unsafe. getUnsafe () ;}------------------- // output: Exception in thread "main" java. lang. securityException: Unsafe at sun. misc. unsafe. getUnsafe (Unsafe. java: 90) at concurrent. unsafeDemo. main (UnsafeDemo. java: 7) // analysis: you can find that a security exception is thrown directly when calling directly, because the class loader is AppClassLoader rather than BootstrapLoader.

 

  • According to the working principle of the Java class loader, the application class is loaded by AppLoader, and the system core class is loaded by BootstrapLoader.
  • When the class loader of a class is null, it indicates that it is loaded by BootstrapLoader, that is, this class is the system core class (such as the class in the rt. jar package)
  • When a class cannot be loaded by BootstrapLoader, its class loader is usually AppClassLoader, which is a custom class.

 

UnsafeReflection acquisition

/*** We can obtain an Unsafe instance through the reflection mechanism */public static Unsafe getUnsafe () {try {// obtain the Unsafe theUnsafe variable through reflection, that is, the Unsafe instance object Field f = Unsafe. class. getDeclaredField ("theUnsafe"); f. setAccessible (true); // note that the field is static. // For details, see private static final Unsafe theUnsafe; return (Unsafe) f. get (null);} catch (Exception e) {e. printStackTrace ();} return null ;}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.