1. 程式人生 > 實用技巧 >JAVA Unsafe類

JAVA Unsafe類

Unsafe類原始碼的自我認知:

這個Unsafe類位於package sun.misc包中

Unsafe使用了1個介面,4個類

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import sun.reflect.CallerSensitive; //該為介面
import sun.reflect.Reflection;

從如下定義方式可知,該類是final型別的變數,那麼也就是無法繼承的!

public final class Unsafe

Unsafe定義了一堆如下屬性,需要注意的是theUnsafe

private static final Unsafe theUnsafe; //這個屬性儲存了一個Unsafe物件,為什麼呢?繼續看後面
public static final int INVALID_FIELD_OFFSET = -1;
public static final int ARRAY_BOOLEAN_BASE_OFFSET;
public static final int ARRAY_BYTE_BASE_OFFSET;
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 ARRAY_FLOAT_BASE_OFFSET;
public static final int ARRAY_DOUBLE_BASE_OFFSET;
public static final int ARRAY_OBJECT_BASE_OFFSET;
public static final int ARRAY_BOOLEAN_INDEX_SCALE;
public static final int ARRAY_BYTE_INDEX_SCALE;
public static final int ARRAY_SHORT_INDEX_SCALE;
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 ARRAY_FLOAT_INDEX_SCALE;
public static final int ARRAY_DOUBLE_INDEX_SCALE;
public static final int ARRAY_OBJECT_INDEX_SCALE;
public static final int ADDRESS_SIZE;

它的建構函式是私有的,這就導致了它無法進行共有的例項化

它有一個getUnsafe方法來進行獲取本身

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

它定義了一大堆的getter setter屬性的方法,不止如下圖所示的數量

我還看到了它關於操控記憶體的方法,如下方法



public native long allocateMemory(long var1); //分配記憶體
public native 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);
}
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);
}
public native void freeMemory(long var1); //釋放記憶體

還有三個特殊的如下方法:

public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6); //定義類
public native Class<?> defineAnonymousClass(Class<?> var1, byte[] var2, Object[] var3); //定義匿名類
public native Object allocateInstance(Class<?> var1) throws InstantiationException; //分配例項

靜態程式碼塊,這裡就要講為什麼theUnsafe會儲存一個Unsafe物件了

static {
        registerNatives();
        Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
        theUnsafe = new Unsafe(); //這裡就說明了為什麼theUnsafe會儲存一個Unsafe物件
        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();
    }

我查了下靜態程式碼塊的概念:static程式碼塊指的是static{}包裹的程式碼塊,且靜態程式碼只執行一次,可以通過Class.forName("classPath")的方式喚醒程式碼的static程式碼塊,但是也執行一次

我等下需要做個試驗來證明是不是隻有Class.forName("classPath")來喚醒static程式碼塊還是咋的