当前位置:网站首页>How magical is the unsafe class used by all major frameworks?

How magical is the unsafe class used by all major frameworks?

2022-04-23 16:20:00 JAVA Chinese community

Preface

Almost everyone uses Java Development tools 、 Software infrastructure 、 High performance development libraries are used at the bottom sun.misc.Unsafe, such as Netty、Cassandra、Hadoop、Kafka etc. .

Unsafe Class is upgrading Java Operational efficiency , enhance Java The language bottom level operation ability aspect has played the very big role . but Unsafe Class in sun.misc It's a bag , Do not belong to Java standard .

A long time ago , When reading the source code of concurrent programming related classes , notice Unsafe class , There was a doubt : Since it is a class used in concurrent programming , Why is it named Unsafe Well ?

I don't know until I know more about it , there Unsafe It's not about thread safety , But to : This class is common to programmers ” dangerous “ Of , General application developers will not and should not use this kind of .

because Unsafe Class is too powerful , Provides some ways to bypass JVM Lower level functions of . It makes Java Have something like C The ability to manipulate memory space like a pointer to a language , Can improve efficiency , But it also brings the problem of pointers . The official does not recommend the use of , No documentation support , It is even planned to remove this class in the later version .

But for developers , Understanding the functions provided by this class is more helpful for us to learn CAS、 Concurrent programming and other related knowledge , It is still very necessary to learn and understand .

Unsafe Construction

Unsafe Class is "final" Of , Inheritance is not allowed , And the constructor is private, The singleton pattern is used to pass through a static method getUnsafe() To get .

private Unsafe() {
    }

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class var0 = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
            throw new SecurityException("Unsafe");
        } else {
            return theUnsafe;
        }
    }

stay getUnsafe Method limits the creation of objects in singleton mode , If it is an ordinary call, it will throw a SecurityException abnormal . Only classes loaded by the main class loader can call this method .

that , How to get Unsafe Class objects ? Reflection mechanism is usually used :

public static Unsafe getUnsafe() throws IllegalAccessException {
  Field unsafeField = Unsafe.class.getDeclaredFields()[0];
  unsafeField.setAccessible(true);
  return (Unsafe) unsafeField.get(null);
}

When you get Unsafe After object , Can ” Do as one pleases “ 了 . So let's see , adopt Unsafe Method , What can we do .

Unsafe The main function of

Let's take a look at the picture below as a whole Unsafe Features provided :

98efed0cda6c70adb531b0c4a5c51a5d.png
Unsafe Function Overview

Now select the important functions to explain .

One 、 memory management

Unsafe The main memory management functions include : Ordinary reading and writing 、volatile Reading and writing 、 Orderly write 、 Direct operation of memory and other functions of allocating and releasing memory .

Ordinary reading and writing

Unsafe You can read and write the properties of a class , Even if this property is private , You can also read and write this property .

//  Get the integer the memory address points to 
public native int getInt(Object var1, long var2);

//  Write the integer to the specified memory address 
public native void putInt(Object var1, long var2, int var4);

getInt Used to read a... From the specified offset address of an object int.putInt Used to write a... At the specified offset address of an object int. Other primitive types also provide corresponding methods .

in addition ,Unsafe Of getByte、putByte Method provides the function of reading and writing directly on an address .

volatile Reading and writing

Ordinary reading and writing cannot guarantee visibility and order , and volatile Reading and writing ensures visibility and order .

//  Get the integer the memory address points to , And support volatile semantics 
public native int getIntVolatile(Object var1, long var2);

//  Write the integer to the specified memory address , And support volatile semantics 
public native void putIntVolatile(Object var1, long var2, int var4);

volatile Read and write to ensure visibility and order , It's more expensive than ordinary reading and writing .

Orderly write

Orderly writing only ensures the order of writing , Visibility is not guaranteed , That is, the writing of one thread does not guarantee that other threads are immediately visible .

//  Write the integer to the specified memory address 、 Orderly or delayed methods 
public native void putOrderedInt(Object var1, long var2, int var4);

And with the volatile Write comparison putOrderedXX The cost of writing is relatively low ,putOrderedXX Writing does not guarantee visibility , But ensure order , Order , Is to ensure that the instructions are not reordered .

Direct memory operation

Unsafe Provides the ability to directly manipulate memory :

//  Allocate memory 
public native long allocateMemory(long var1);
//  Reallocate memory 
public native long reallocateMemory(long var1, long var3);
//  Memory initialization 
public native void setMemory(long var1, long var3, byte var5);
//  Memory copy 
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);
//  Clear memory 
public native void freeMemory(long var1);

Corresponding operation memory , It also provides some methods to obtain memory information :

//  Get memory address 
public native long getAddress(long var1);

public native int addressSize();

public native int pageSize();

It is worth noting that : utilize copyMemory Method can implement a general object copy method , There's no need to implement... For every object clone Method , But you can only make shallow copies of objects .

Two 、 Unconventional object instantiation

Usually , We go through new Or reflection to instantiate objects , and Unsafe Class provides the allocateInstance Method , Object instances can be generated directly , And there is no need to call the construction method and other initialization methods .

This is useful when deserializing objects , Able to rebuild and set up final Field , Instead of calling the constructor .

//  Generate object instances directly , The constructor of this instance will not be called 
public native Object allocateInstance(Class<?> var1) throws InstantiationException;

3、 ... and 、 Class loading

By , You can implement the definition of classes 、 Create and so on .

//  Method to define a class , Used to dynamically create classes 
public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);

//   Dynamically create an anonymous inner class 
public native Class<?> defineAnonymousClass(Class<?> var1, byte[] var2, Object[] var3);

//  Determine whether a class needs to be initialized 
public native boolean shouldBeInitialized(Class<?> var1);

//  Ensure that a class has been initialized 
public native void ensureClassInitialized(Class<?> var1);

Four 、 Offset related

Unsafe Provide the following methods to get the pointer of the object , By offsetting the pointer , Not only can you directly modify the data pointed to by the pointer ( Even if they are private ), You can even find JVM Has been identified as garbage 、 Objects that can be recycled .

//  Get static properties Field The offset in the object , When reading and writing a static property, you must obtain its offset 
public native long staticFieldOffset(Field var1);
//  Get non static properties Field The offset in the object instance , This offset is used when reading and writing non static properties of an object 
public native long objectFieldOffset(Field var1);
//  return Field Where you are 
public native Object staticFieldBase(Field var1);
//  Returns the offset of the actual address of the first element in the array from the address of the entire array object 
public native int arrayBaseOffset(Class<?> var1);
//  Calculate the memory space occupied by the first element in the array 
public native int arrayIndexScale(Class<?> var1);

5、 ... and 、 Array operation

The array operation provides the following methods :

//  Get the offset address of the first element of the array 
public native int arrayBaseOffset(Class<?> var1);
//  Get the incremental address of the element in the array 
public native int arrayIndexScale(Class<?> var1);

arrayBaseOffset And arrayIndexScale Use in conjunction with , You can locate the location of each element in the array in memory .

because Java The maximum value of the array of is Integer.MAX_VALUE, Use Unsafe Class can implement large arrays . In fact, such data can be considered as C Array , So pay attention to freeing memory at the right time .

6、 ... and 、 Thread scheduling

The related methods of thread scheduling are as follows :

//  Wake up the thread 
public native void unpark(Object var1);
//  Hung thread 
public native void park(boolean var1, long var2);
//  For locking , obsolete 
public native void monitorEnter(Object var1);
//  For locking , obsolete 
public native void monitorExit(Object var1);
//  For locking , obsolete 
public native boolean tryMonitorEnter(Object var1);

adopt park Method to suspend the thread , The thread will block until a timeout or interrupt condition occurs .unpark Method can terminate a suspended thread , Bring it back to normal .

The pending operations on threads in the whole concurrency framework are encapsulated in LockSupport Class ,LockSupport There are various versions of... In the class pack Method , But in the end it all calls Unsafe.park() Method .

7、 ... and 、CAS operation

Unsafe Class CAS Operation is probably the most used method . It's for Java A new solution is provided by the lock mechanism of , such as AtomicInteger All classes are implemented through this method .compareAndSwap The method is atomic , Can avoid heavy locking mechanism , Improve code efficiency .

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

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);

CAS Generally used for optimistic locks , It's in Java Widely used in ,ConcurrentHashMap,ConcurrentLinkedQueue All of them are useful for CAS To achieve the optimistic lock .

8、 ... and 、 Memory barrier

JDK8 New to define memory barriers 、 Ways to avoid code rearrangement :

//  Make sure that all read operations before this barrier have been completed 
public native void loadFence();

//  Ensure that all write operations before this barrier have been completed 
public native void storeFence();

//  Ensure that all read and write operations before this barrier have been completed 
public native void fullFence();

Nine 、 other

Of course ,Unsafe Class also provides a number of other methods , As mentioned above CAS operation , With AtomicInteger For example , When we call getAndIncrement、getAndDecrement Other methods , What is called is Unsafe Of getAndAddInt Method .

public final int getAndIncrement() {
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

public final int getAndDecrement() {
    return unsafe.getAndAddInt(this, valueOffset, -1);
}

In the process of practice , If you read other frameworks or class library implementations , When found to use Unsafe class , It can be compared with the overall function of this class , Analyze in combination with application scenarios , You can roughly understand its function .

Summary

After the analysis of this paper , You must be reading the source code , Meet again Unsafe Class , You must probably guess what it is used for . Use Unsafe The main purpose of class is to improve operation efficiency in most cases 、 Enhancements . But it also faces mistakes 、 Memory management and other risks . Only in-depth understanding , And it is recommended to use only when necessary .

a9ab3e1e3851ad3ea1c562e9bf614c0d.gif

 Previous recommendation 

9d68c4ea64e912521fd269b0af8ee57b.png

synchronized How is the underlying implementation ?


5a6a2289ff8ac39a6f7e1c7d5a1a33b3.png

Thread sleep has 5 Methods ?


3eb1a75c62aaa1152a84db48867d4f76.png

Shrimp noodles : What is zero copy ? How to achieve zero copy ?


fdae7600e60f4cd10b62decaff0bc3e8.gif

版权声明
本文为[JAVA Chinese community]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231617546835.html