Java 1.8 & Android Oreo 常用源码分析

Java8 Unsafe 解开你神秘的面纱

2018-09-17  本文已影响16人  没有颜色的菜

前言

Unsafe 类一直是个很神秘的角色,我们普通开发者几乎不会碰到,顶多也是使用了并发包之类的系统类库,间接使用到了而已。那它到底是用来做什么的呢?它提供了我们直接操作内存的接口。Java 本身作为一个内存自动管理的工具,内存的开辟释放由虚拟机代为管理,然而,HotSpot 的设计者留下了 Unsafe 的类,用于扩展,它可以直接开辟内存,释放内存,读取任意地址的内存,而不受 Java 堆内存的限制。尽管如此,它并不能为我们所用,加载这个类只能由系统的类加载器执行,但我们可以通过反射获取到它的实例对象,Java 反射的确很牛啊。

如何获取实例对象

第一个问题:为什么我们需要通过 Field 获取,不能使用 newInstance 获取呢?
通过 newInstance 的方法获取实力需要构造函数是 public 的,否则会抛异常,及时 getUnsafe 是静态函数,我们也不能通过这个去获取,因为这时候类加载不是系统的,会抛异常

    private Unsafe() {
    }

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

由于 Unsafe 是单例,当类加载时,theUnsafe 实例会被加载,这样我们就可以通过反射获取这个实例

    static {
        registerNatives();
        Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
        // 重点
        theUnsafe = new Unsafe();
    }

通过 Field 获取

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
    }

获取到这实例,就可以干很多事情了.....
先来看看 API 图


Screen Shot 2018-09-16 at 11.20.42 PM.png Screen Shot 2018-09-16 at 11.20.59 PM.png Screen Shot 2018-09-16 at 11.21.15 PM.png

太多了,眼睛都看瞎了
归个类吧

        String str = "Hello Unsafe";
        Field value = str.getClass().getDeclaredField("value");
        unsafe.putObject(str, unsafe.objectFieldOffset(value), new char[]{'M', 'a', 'j', 'i', 'c'});]
        System.out.println(str);
        // output: Majic

        // throw exception
        String str = "Hello Unsafe";
        Field value = str.getClass().getDeclaredField("value");

        value.setAccessible(true);
        value.set(str, new char[] {'f', 'i', 'n', 'a', 'l'});
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);
        InnerClass o = (InnerClass)unsafe.allocateInstance(InnerClass.class);
        o.print(); // print 100
        Field a = o.getClass().getDeclaredField("value");
        unsafe.putLong(o, unsafe.objectFieldOffset(a), 10000);
        o.print(); // print 10000
        unsafe.compareAndSwapLong(o, unsafe.objectFieldOffset(a), 10000, 1111);
        o.print(); // print 1111
        unsafe.compareAndSwapLong(o, unsafe.objectFieldOffset(a), 1000, 10000);
        o.print(); // print 1111
    }
     
    static class InnerClass {
        // 保证内存可见性
        private volatile long value;
        InnerClass() {
            value = 100L;
        }
        void print() {
            System.err.println("value==>" + value);
        }
    }
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException, InterruptedException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);
        Unsafe unsafe = (Unsafe) theUnsafe.get(null);

        InnerThread innerThread = new InnerThread(unsafe);
        innerThread.run();

        Thread.sleep(20);
        // 取消挂起
        unsafe.unpark(innerThread);
    }

    static class InnerThread extends Thread {
        Unsafe unsafe;

        InnerThread(Unsafe unsafe) {
            this.unsafe = unsafe;
        }

        @Override
        public void run() {
            System.out.println("start");
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //unsafe.park(false, 1000000000L);
            System.out.println("end");
        }
    }

小结

以后又可以吹一波了,一箭双雕,反射,Unsafe

上一篇 下一篇

猜你喜欢

热点阅读