Unsafe的使用解析

2018-12-10  本文已影响0人  braveheart075

相信很多人都阅读过jdk源码,这两天在看一段代码都时候正好用到Unsafe(JRE的rt.jar中提供了一个类sun.misc.Unsafe),特地研究了下Unsafe这个类。基于对象内存来进行操作对象。不安全。所以不建议使用。特别在concurrent包中都Atomicxxx类,底层都CAS 都用到了这个类。那么这个类究竟能干什么,我们先从实例化开始:

        sun.misc.Unsafe U = null;

        Field theUnsafeInstance = null;
        try {
            theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeInstance.setAccessible(true);
            U = (Unsafe) theUnsafeInstance.get(Unsafe.class);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
public class Main {


    private String s;
    private long s1;
    private long s2;

    public static void main(String[] args) {
        Main main = new Main();
        main.s1 = 20;
        long s, next;
        long state = 256;
        System.out.println(1 << 6);
        System.out.println(1 << 10);
        System.out.println(1L << 7);
        System.out.println("Hello World!");
        long except = 1;
        long real = 1;
        sun.misc.Unsafe U = null;

        Field theUnsafeInstance = null;
        try {
            theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeInstance.setAccessible(true);
            U = (Unsafe) theUnsafeInstance.get(Unsafe.class);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        System.out.println("========");

//        Arrays.stream(Main.class.getDeclaredFields()).forEach(field -> System.out.println(U.objectFieldOffset(field.getName())));

        Field[] fields = Main.class.getDeclaredFields();
        for(Field field : fields) {

            System.out.println(field.getName()+ "=="+ U.objectFieldOffset(field));
        }


        System.out.println("========");


        boolean flag = U.compareAndSwapLong(main,16,21,21);
        System.out.println(flag);
        System.out.println(main.s1);

    }
}
Field[] fields = Main.class.getDeclaredFields();
        for(Field field : fields) {

            System.out.println(field.getName()+ "=="+ U.objectFieldOffset(field));
        }

打印出来的结果如下:

s==12
s1==16
s2==24

这个数字就是offset。那么我们可以验证这个compare方法了。

boolean flag = U.compareAndSwapLong(main,16,20,21);
System.out.println(flag);
System.out.println(main.s1);

就是比较偏移量为16的内存对象值是否是20,如果是,改成21,打印结果如下:

true
21

可以看到,如预期。好了,大家都知道类似的方法怎么用了吧。期望对大家有帮助。

上一篇下一篇

猜你喜欢

热点阅读