sun.misc.Unsafe understanding

1, the role of class Unsafe

Can operate directly outside the heap memory, and data structures can be viewed freely modify the run time of the JVM, such as view and modify objects members, the Unsafe operation size is not a class, but the data and address.

Further, also supports atomic operations CAS

2, get Unsafe objects

Unsafe can not get directly through the new Unsafe () or by calling Unsafe.getUnsafe (), for the following reasons:

Unsafe not directly new new, because Unsafe embodiment is designed to be single mode, the constructor is private

Not by calling Unsafe.getUnsafe () Gets because getUnsafe is designed to be loaded only from the boot class loader (bootstrap class loader), can be seen from getUnsafe source as follows:

public  static the Unsafe getUnsafe () {
         // get the class object that calls the method 
        Class varO = Reflection.getCallerClass ();
         // determine whether the class is called the method bootstrap class loader (class on Bootstrap Loader)
         // if not, such the method is called by the AppClassLoader, then a SecurityException 
        IF (! VM.isSystemDomainLoader (var0.getClassLoader ())) {
             the throw  new new SecurityException ( "the Unsafe" ); 
        } the else {
             return theUnsafe; 
        } 
    } 
    public  static  Boolean isSystemDomainLoader (ClassLoader varO) {
         returnvar0 == null ; 
    }

Although the method can not be obtained by the upper Unsafe object, but some Private Unsafe class has a static global attributes theUnsafe (Unsafe instance object), by reflection, the object can be acquired Field theUnsafe attribute corresponding to the member, and which is provided to be accessible to give theUnsafe particular subject.

Package Concurrency; 

Import as java.lang.reflect.Field;
 Import sun.misc.Unsafe;
 Import sun.reflect.Reflection; 

public  class the Test {
     public  static  void main (String [] args) throws a NoSuchFieldException, 
            a SecurityException, an IllegalArgumentException, IllegalAccessException { 
        / / by reflection theUnsafe Field object corresponding 
        Field Field = the Unsafe. class .getDeclaredField ( "theUnsafe" );
         // set up to access the Field 
        field.setAccessible ( to true );
         //Field of the concrete object obtained by Field corresponding null is passed in as static because Field of 
        the Unsafe the unsafe = (the Unsafe) Field.get ( null ); 
        System.out.println (the unsafe); 

    } 
}

3, Unsafe class Api

allocateInstance方法,不调用构造方法生成对象

Native methods, the ability to create an object instance, but does not run the constructor of the object; due natUnsafe.cc older version, did not find the corresponding c ++ implementation;

/** Allocate an instance but do not run any constructor. Initializes the class if it has not yet been. */
    public native Object allocateInstance(Class cls)
        throws InstantiationException;

Example, the use of allocateInstance Unsafe methods, became the object constructor is not invoked in the case of swells:

package concurrency;

import java.lang.reflect.Field;

import sun.misc.Unsafe;
import sun.reflect.Reflection;

class User {
    private String name = "";
    private int age = 0;

    public User() {
        this.name = "test";
        this.age = 22;
    }
    
    @Override
    public String toString() {
        return name + ": " + age;
    }
}


public class Test {
    public static  void main (String [] args) throws a NoSuchFieldException, 
            a SecurityException, an IllegalArgumentException, IllegalAccessException, an InstantiationException is { 
        // get theUnsafe corresponding to the object by reflecting Field 
        Field Field = the Unsafe. class .getDeclaredField ( "theUnsafe" );
         // set to the Field access 
        field.setAccessible ( to true );
         // by Field Field of the obtained corresponding to the object-specific, null is passed in as static because Field of 
        the Unsafe the unsafe = (the Unsafe) Field.get ( null ); 

        the User User = (the User) unsafe.allocateInstance (the User. class );
        System.out.println(user); //dont invoke constructor, print null: 0
        
        User userFromNormal = new User();
        System.out.println(userFromNormal); //print test: 22

    }
}

objectFieldOffset method returns the address in memory member property with respect to the memory address offset of the object

Is relatively simple, is the return address of member properties with respect to the memory offset address of the memory object, an object may be calculated in the memory space by this method, it is obtained by reflection of all the Field (including the parent class inherited) find the maximum offset in Field, then filled with the number of bytes is the size of the object value of the maximum offset;

Examples on the use of the method may modify the memory data, see examples below;

putLong, putInt, putDouble, putChar, putObject and other methods to directly modify the data memory (can cross access)

Here, there are put the corresponding get method, was simply to directly read the data at the memory address, for example not;

 We can give putLong (Object, long, long) method detailed look at specific implementation, other similar, look at the Java source code, nothing nice, it declares a native native method:

Description the three parameters:

Object o // object reference
Long offset // offset address memory objects
Data written long x //
public native void    putLong(Object o, long offset, long x);

Or look natUnsafe.cc in c ++ realize it, very simply, it is to calculate the address of the data to be written to memory, and then write the data, as follows:

void 
Sun the Unsafe :: :: :: Misc putLong (obj jobject, jlong offset, jlong value) 
{ 
  jlong * addr = (jlong *) (( char *) obj + offset); // calculate the modified data to memory address target address = address + offset member attribute 
  the spinlock lock; // spin locks, locks acquired by the circulation, i386 processor needs to access 64-bit lock data, and if int, the codes do not need to be diverted 
  * addr = value; // write data directly to the memory address location 
}

As an example, even if the member property of the User class is private and does not provide external public method, we can write directly at their location data memory address, and success;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class User {
    private String name = "wangwp";
    private int age = 12;
    private double height = 1.61;

    @Override
    public String toString() {
        return name + "," + age + "," + height;
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //通过反射得到unsafe对应的field对象
        Field field = Unsafe.class .getDeclaredField ( "theUnsafe" );
         // set the field to access 
        field.setAccessible ( to true );
         // get specific field corresponding to the object by the field, because this field is null is passed to the static 
        Unsafe unsafe = (Unsafe ) Field.get ( null ); 

        the User User = new new the User (); 
        System.out.println (User); // wangwp, 12,1.61 

        // Class userClass = User.class; 
        Class userClass = user.getClass (); 

        name Field, = userClass.getDeclaredField ( "name" ); 
        Field, Age = userClass.getDeclaredField ( "Age" );
        Field height = userClass.getDeclaredField("height");

        //直接往内存地址写数据
        unsafe.putObject(user, unsafe.objectFieldOffset(name), "gaogao");
        unsafe.putInt(user, unsafe.objectFieldOffset(age), 23);
        unsafe.putDouble(user, unsafe.objectFieldOffset(height), 1.98);

        System.out.println(user);//gaogao,23,1.98

    }
}

copyMemory、freeMemory

copyMemory:内存数据拷贝

freeMemory:用于释放allocateMemory和reallocateMemory申请的内存

 CAS操作的方法,compareAndSwapInt,compareAndSwapLong等

看下natUnsafe.cc中的c++实现吧,加深理解,其实就是将内存值与预期值作比较,判断是否相等,相等的话,写入数据,不相等不做操作,返回旧数据;

static inline bool
compareAndSwap (volatile jint *addr, jint old, jint new_val)
{
  jboolean result = false;
  spinlock lock;
  if ((result = (*addr == old)))
    *addr = new_val;
  return result;
}

JUC in CAS-atomic operation based on the above implementation;

getLongVolatile / putLongVolatile like method

Such methods use volatile access to semantic data, I understand that each thread does not cache data, reading data directly in the memory;

Guess you like

Origin www.cnblogs.com/cherish010/p/11059019.html