美文网首页
Unsafe这个神奇的类

Unsafe这个神奇的类

作者: idolice24 | 来源:发表于2018-10-10 11:37 被阅读0次

    这个类啊是在并发包里很多类都用到的一个类,打开一看,莫名其妙,全是native定义的方法,作用是啥,怎么用?一堆问题,慢慢看了几篇文章,有了滴滴头绪~

    听这个名字就知道,这是一个不安全的类,而且由于它设置了保护机制,我们一般的类是没办法使用它的(也不是真的没办法,好多地方也悄悄用了,只是正常情况下没办法使用),所以我们就了解一下就是了,它是怎么拒绝一般的类使用它的呢?

    首先,它只有一个private的构造函数,然后它自己内部维护了一个自身的实例,想要获取这个实例的话,有如下方式:

    @CallerSensitive

    public static Unsafe getUnsafe() {

        Class var0 = Reflection.getCallerClass();

        if (!VM.isSystemDomainLoader(var0.getClassLoader())) {

            throw new SecurityException("Unsafe");

        } else {

            return theUnsafe;

        }

    }

    VM.isSystemDomainLoader(var0.getClassLoader())这个方法呢就是去检查调用次方法的类的类加载器是否是bootstrap classloader,如果不是的话,就抛异常,大家都知道,bootstrap classloader它负责加载Java的核心类,我们一般的类用的是系统类加载器,所以这里就没法继续了(再次申明,正常情况没法继续,有一些黑方法是可以的,但是我不想展开讲,因为又要写一大堆,如果想知道就留言,有人想看我再写~),这个类调用的都是系统本地接口,其他语言实现的,我们这儿在源码里也看不到(想看也能找到),所以洗洗睡吧~

    咳咳,然后这个Unsafe类的作用是什么呢?

    可多了,每个方法都有自己的作用(可能有些人想打我=。=)

    So,举几个例子吧(从国外的文章搬过来给小伙伴们欣赏https://dzone.com/articles/understanding-sunmiscunsafe

    首先它能在不通过调用构造函数的情况下创建一个对象实例:

    class ClassWithExpensiveConstructor {

      private final int value;

      private ClassWithExpensiveConstructor() {

        value = doExpensiveLookup();

      }

      private int doExpensiveLookup() {

        try {

          Thread.sleep(2000);

        } catch (InterruptedException e) {

          e.printStackTrace();

        }

        return 1;

      }

      public int getValue() {

        return value;

      }

    }

    @Test

    public void testObjectCreation() throws Exception {

      ClassWithExpensiveConstructor instance = (ClassWithExpensiveConstructor)

      unsafe.allocateInstance(ClassWithExpensiveConstructor.class);

      assertEquals(0, instance.getValue());

    }

    可以看到,通过allocateInstance这个方法就这么生成了一个实例instance,炒鸡方便有木有(其实并没有什么了不起,反射完爆一切~)。好吧,这篇文章展示了这么一个方法,什么时候用到也未知,大概率你一辈子也不会用到。。。

    后面这个功能呢,就要牛逼很多了,就是分配内存!大家都知道,java里面呢,有那么几个原始的数据类型,大小呢也是固定的,比如int就4个字节,最大值也就Integer.MAX_VALUE,

    那么,我们想要那么一个数字,最大值是超越了Integer.MAX_VALUE的话就要想别的方法啦(别说这种情况很少遇到,凡事都有例外呢~)

    那么恰好呢,这个Unsafe类就提供了那么些方法,我们来看个例子:

    class DirectIntArray {

      private final static long INT_SIZE_IN_BYTES = 4;

      private final long startIndex;

      public DirectIntArray(long size) {

        startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);

        unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);

        }

      }

      public void setValue(long index, int value) {

        unsafe.putInt(index(index), value);

      }

      public int getValue(long index) {

        return unsafe.getInt(index(index));

      }

      private long index(long offset) {

        return startIndex + offset * INT_SIZE_IN_BYTES;

      }

      public void destroy() {

        unsafe.freeMemory(startIndex);

      }

    }

    @Test

    public void testDirectIntArray() throws Exception {

      long maximum = Integer.MAX_VALUE + 1L;

      DirectIntArray directIntArray = new DirectIntArray(maximum);

      directIntArray.setValue(0L, 10);

      directIntArray.setValue(maximum, 20);

      assertEquals(10, directIntArray.getValue(0L));

      assertEquals(20, directIntArray.getValue(maximum));

      directIntArray.destroy();

    }

    通过allocateMemory方法,就可以分配相应字节的内存啦,然后再通过unsafe.setMemory就可以给分配好的内存赋值,假如你想按着int类型的数据也就是4个字节4个字节赋值可以调用unsafe.putInt,这个是不是还蛮有用的?

    在开头我说了,并发包里好多类在对于关键字段的修改上都用了Unsafe类的方法,所以,关键的来了哦,就是以下一些方法:

    public final native booleancompareAndSwapObject(Object var1, longvar2,Object var4,Object var5);

    public final native booleancompareAndSwapInt(Object var1, longvar2, intvar4, intvar5);

    public final native booleancompareAndSwapLong(Object var1, longvar2, longvar4, longvar6);

    看名字就知道,跟CAS脱不了关系啦,以及还有一些这种方法:

    public native intgetIntVolatile(Object var1, longvar2);

    public native voidputIntVolatile(Object var1, longvar2, intvar4);

    看名字就知道,和Volatile也有关系啦,不知道CAS和Volatile的去面壁吧~

    所以说呢,并发包就是用Unsafe的这些方法去保证他们关键字段操作的线程安全而已,方法就那些,所以大家就散了吧~

    相关文章

      网友评论

          本文标题:Unsafe这个神奇的类

          本文链接:https://www.haomeiwen.com/subject/gtrpaftx.html