JDK的Unsafe類的一些用法總結

JDK的rt.jar包中的Unsafe類提供了硬件級別的原子性操作,Unsafe類中的方法都是native方法,
它們使用JNI的方式訪問本地C++ 實現庫。

錯誤代碼示範:

public class TestUnSafe {
/*********
     * 直接下面這種方式會報錯:原因是我們自己寫的類是由AppClassLoader類加載器加載;
     * 而UnSafe類的getUnsafe()爲了保證rt包的安全;Unsafe類可以直接操作內存;
     * 不讓開發人員在正規渠道使用Unsafe類,而是在rt.jar包裏面的核心類中使用Unsafe功能。
	     	@CallerSensitive
		    public static Unsafe getUnsafe() {
		        Class var0 = Reflection.getCallerClass();
		        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
		            throw new SecurityException("Unsafe");
		        } else {
		            return theUnsafe;
		        }
		    }
     *   改爲後面的反射方式獲取theUnsafe成員變量
     *   java.lang.ExceptionInInitializerError
         *  Caused by: java.lang.SecurityException: Unsafe
         * 	at sun.misc.Unsafe.getUnsafe(Unsafe.java:90)
         * 	at com.liang.unsafe.TestUnSafe.<clinit>(TestUnSafe.java:12)
         * Exception in thread "main"
    *******/
    //獲取Unsafe的實例
    static final Unsafe unsafe = Unsafe.getUnsafe();

    //記錄變量state在類TestUnSafe中的偏移值
    static final long stateOffset;

    private volatile long state = 0;

    static {
        try {
            System.out.println(TestUnSafe.class.getClassLoader());
            stateOffset = unsafe.objectFieldOffset(TestUnSafe.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            System.out.println(e.getCause());
            throw new Error(e);
        }
    }
    public static void main(String[] args) {

        // 創建實例,並設置state值爲1
        TestUnSafe testUnSafe = new TestUnSafe();
        Boolean success = unsafe.compareAndSwapLong(testUnSafe,stateOffset,0,1);

        System.out.println(success);
    }
}

正確代碼示範:

public class TestUnSafe {
    //獲取Unsafe的實例
    static Unsafe unsafe;

    //記錄變量state在類TestUnSafe中的偏移值
    static long stateOffset;

    private volatile long state = 0;

    static {
        try {
            // 使用反射獲取Unsafe的成員變量theUnsafe
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            //設置爲可讀取
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);

            // 獲取state 在 TestUnSafe中的偏移量
            stateOffset = unsafe.objectFieldOffset(TestUnSafe.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            System.out.println(e.getCause());
            throw new Error(e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        System.out.println(TestUnSafe.class.getClassLoader());
        // 創建實例,並設置state值爲1
        TestUnSafe testUnSafe = new TestUnSafe();
        Boolean success = unsafe.compareAndSwapLong(testUnSafe,stateOffset,0,1);
        System.out.println(success);
		// 返回指定的變量在所屬類中的內存偏移地址,該偏移地址僅僅在該Unsafe函數中訪問指定字段時使用。
        System.out.println(unsafe.objectFieldOffset((AtomicLong.class.getDeclaredField("value"))));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章