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.(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"))));
    }
}

你可能感兴趣的:(源码研究,JavaCore)