Unsafe

作者: Jokerone_ | 来源:发表于2017-04-16 14:38 被阅读0次

前言

Java最初被设计成一种安全的受控环境。尽管如此,HotSpot还是包换了一个后门sun.misc.Unsafe,提供了一些可以直接操控内存和线程的底层操作。Unsafe被JDK广泛应用于java.nio和并发包等实现中,这个不安全的类提供了一个观察HotSpot JVM内部结构并且可以对其进行修改,但是不建议在生产环境中使用。

如何使用

unsafe类是如此地不安全,以至于JDK开发者增加了很多特殊限制来访问它。

1.私有的构造器
2.工厂方法getUnsafe()的调用器只能被Bootloader加载,否则抛出SecurityException 异常

    @CallerSensitive
    public static Unsafe getUnsafe() {
        //得到调用该方法的Class对象
        Class cc = Reflection.getCallerClass();
        //判断调用该方法的类是否是引导类加载器(bootstrap class loader)
        //如果不是的话,比如由AppClassLoader调用该方法,则抛出SecurityException异常
        if (cc.getClassLoader() != null)
            throw new SecurityException("Unsafe");
        //返回单例对象
        return theUnsafe;
    }

不过,我们可以通过反射机制轻松获取Unsafe的一个实例。

public static Unsafe getUnsafe() {
   try {
           Field f = Unsafe.class.getDeclaredField("theUnsafe");
           f.setAccessible(true);
           return (Unsafe)f.get(null);
   } catch (Exception e) { 
       /* ... */
   }
}

一些有用的方法

objectFieldOffset:能够获取到指定实例变量的在对象内存中的偏移量

long offset = UNSAFE.objectFieldOffset(UnsafeTest.class.getDeclaredField("state"));

compareAndSwapInt:通过比较并替换的机制,修改指定偏移量内存的值

UNSAFE.compareAndSwapInt(unsafeTest, offset, 0, 1)

park:挂起某一线程
unpark:唤醒某一线程

示例:

public class UnSafeClassTest {

    public static void main(String[] args) throws NoSuchFieldException,
            SecurityException, IllegalArgumentException, IllegalAccessException {
        // 通过反射得到theUnsafe对应的Field对象
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        // 设置该Field为可访问
        field.setAccessible(true);
        // 通过Field得到该Field对应的具体对象,传入null是因为该Field为static的
        Unsafe unsafe = (Unsafe) field.get(null);
        System.out.println(unsafe);

        byte[] data = new byte[10];
        System.out.println(Arrays.toString(data));
        int byteArrayBaseOffset = unsafe.arrayBaseOffset(byte[].class);

        System.out.println(byteArrayBaseOffset);
        unsafe.putByte(data, byteArrayBaseOffset, (byte) 1);
        unsafe.putByte(data, byteArrayBaseOffset + 5, (byte) 5);
        System.out.println(Arrays.toString(data));

    }
}

参考文章
java中的Unsafe
sun.misc.Unsafe的理解

相关文章

网友评论

      本文标题:Unsafe

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