摘要:Java 中的 Unsafe 是一个特别的类。它提供了很多高效操作内存的功能。Unsafe 从 2002 年引入 Java。它的包名是 sun.misc,表明了这是一个 JDK 的内部类,仅限 JDK 内部的代码使用,并不是提供给外部应用使用的。但是之前的 J
Java 中的 Unsafe 是一个特别的类。它提供了很多高效操作内存的功能。Unsafe 从 2002 年引入 Java。它的包名是 sun.misc,表明了这是一个 JDK 的内部类,仅限 JDK 内部的代码使用,并不是提供给外部应用使用的。但是之前的 Java 版本并没有办法限制应用对内部类的访问。Unsafe 提供的功能实在是非常实用。很多对性能要求高的应用都在用,包括 Apache Hadoop 和 Cassandra。但是,正如 Unsafe 的名字所表示的那样, Unsafe 中的方法都是不安全的。如果错误的使用,轻则可能降低应用的性能;重则可能导致 JVM 的崩溃。Unsafe 是一把强大的双刃剑。
Java 的一个发展方向是保证系统的完整性。其中重要的一环是限制对 JDK 内部类的访问。JDK 9 引入模块系统时,已经对绝大部分的 JDK 内部类进行了封装,但是 Unsafe 是一个例外,因为 Unsafe的使用实在是太广泛。限制 Unsafe 会导致很多应用出现问题。所以对 Unsafe 的限制一直拖了很久。JDK 23 中才把 Unsafe 中的方法声明为废弃的。
在 Java 24 中,当 Unsafe 中与内存访问相关的方法被首次使用时,默认会输出警告信息。
JEP 498
JDK 23 中新增了启动参数 --sun-misc-unsafe-memory-access,这个参数有 4个可选值:allow,warn,debug 和 deny。
在 JDK 23 中,该参数的默认值是 allow,表示允许这些内存访问方法的使用。在 JDK 24 中,该参数的默认值是 warn,表示在使用这些方法时,输出警告信息。debug 表示在每次使用 Unsafe 的内存访问方法时,都会输出警告和 stack trace。如果参数值是 deny,使用这些内存访问方法都会直接抛出 UnsupportedOperationException 。在 JDK 26 中,deny 会变为该参数的默认值。在之后的版本中,这些内存访问方法都会被删除。绝大部分应用都不会直接使用 Unsafe。JDK 中已经提供了 Unsafe 的标准替代方式:
操作 heap 内存时,可以使用 Java 9 引入的 VarHandle。操作 off heap 内存时,可以使用外部方法和内存 API,Java 22 中成为正式功能。如果还有使用 Unsafe的地方,尽快替换成标准的 API。
来源:小鱼科技每日一讲