Java JDK UnSafe 类

JDK 里面有个类你可能没有直接用过, 但是阅读 JDK 源代码的时候, 到某些关键点上, 却经常会遇到, 就是 sun.misc.Unsafe. 这个类为什么不是一个名词呢? 为什么它就像一个警告一样, 告诉你: 不要用, 不要用.

Unsafe 提供了一系列的底层的操作, 这些操作不能像其它正常开放的 API 一样, 能保证安全的操作. Java 9及以后甚至把Unsafe 移到了 jdk.unsupported 的模块去了. (本文基于 Java 8 的 Unsafe 讨论). 因为它的很多操作是不安全的, 所以要求使用它的人, 要明确知道它的危险性在哪, 如何控制这些不安全的操作.

如何获得 Unsafe 实例

Unsafe 是 final 类, 它的构造函数是私有的, 它有个单例对象, 要像获得它, 要通过静态方法 Unsafe. getUnsafe() 方法. 可是这个方法是这么写的:

    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class<?> caller = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
            throw new SecurityException("Unsafe");
        return theUnsafe;
    }

它要求调用 getUnsafe() 方法的对象的类必须是由系统加载器加载的, 否则抛出 SecurityException. 如何做到由系统加载器加载呢?
Java 提供了下面的命令行选项帮助我们把我们期望的类放到系统加载器中加载:

-Xbootclasspath
-Xbootclasspath/a
-Xbootclasspath/p

更多信息, 参考官方文档: https://docs.oracle.com/cd/E15289_01/JRCLR/optionx.htm

如果我们不能控制启动参数呢? 更多的框架等都是通过反射做到的, 比如 Netty 就是类似下面的方式获得 Unsafe 的:

try {
  final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
  unsafeField.setAccessible(true);
  return (Unsafe) unsafeField.get(null);
} catch (Exception e) { //do something }

Unsafe 提供了那些功能?

参考:
https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html
https://www.baeldung.com/java-unsafe
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/sun/misc/Unsafe.java
https://blogs.oracle.com/javamagazine/post/the-unsafe-class-unsafe-at-any-speed

标签: none

添加新评论