在 Java 9 中删除 sun.misc.Unsafe 会破坏 Spring,Hibernate

Removal of sun.misc.Unsafe in Java 9 will break Spring, Hibernate

我读到 here 如果 Oracle 在 Java 9 中删除 sun.misc.Unsafe,Spring 和许多其他流行的库将会中断。但是,没有对此的静态引用class 在 Spring 或休眠中。那么,这种说法是真的吗?

顺便说一句,在 Java 8 中有 64 个对 Unsafe 的引用,但是如果 Oracle 删除那个 class 他们将更新所有这些并且没有库会受到影响(除非他们使用Unsafe直接就是)。

也许引用不在 Spring 或 Hibernate 的核心中,而是在其他地方。链接的文件说 Spring

Spring Framework (via Objenesis, with a fallback)

我试图在我目前正在做的项目中搜索 Unsafe 的用法,所以仍然有很多库可能会崩溃。

快速搜索结果:

  • 番石榴
  • GWT
  • Netty
  • 泽西-通用
  • 无限
  • Jboss-模块

This resource provides a proper understanding of the current status of JDK 9 and its features. The community started a discussion related to Unsafe and its future into the future of java. The given document is the effort of the community to react to JEP-260 建议隐藏一些内部 API 但保留一些关键 API 的可访问性,其中 不安全。从文档本身中提取:

The critical internal APIs proposed to remain accessible in JDK 9 are:

sun.misc.Cleaner

sun.misc.{Signal,SignalHandler}

sun.misc.Unsafe (The functionality of many of the methods in this class is now available via variable handles (JEP 193).)

sun.reflect.Reflection::getCallerClass (The functionality of this method may be provided in a standard form via JEP 259.)

sun.reflect.ReflectionFactory

所以总而言之,至少基于 given JEP,不安全应该保留。

Mark Reinhold 在 2015 年 JVM 语言峰会上发表了题为 The Secret History and Tragic Fate of sun.misc.Unsafe. Although these talks have plenty of disclaimers on them, you can see the proposed approach at 10:23, which is described in JEP260 的演讲。

大意是:

  1. 用更安全、受支持的 API 替换现有功能
  2. 弃用以前存在的 Unsafe API 已被替换
  3. 在下一版本中删除已弃用的代码

以下是 JEP260 中的一些相关文本(取自 2015 年 10 月 20 日):

In JDK 9 we propose to:

  • Encapsulate all non-critical internal APIs by default: The modules that define them will not export their packages for outside use. (Access to such APIs will be available, as a last resort, via a command-line flag at both compile time and run time, unless those APIs are revised or removed for other reasons.)

  • Encapsulate critical internal APIs for which supported replacements exist in JDK 8, in the same manner and with the same last-resort workaround. (A supported replacement is one that is either part of the Java SE 8 standard (i.e., in a java.* or javax.* package) or else JDK-specific and annotated with @jdk.Exported (typically in a com.sun.* or jdk.* package).)

  • Not encapsulate critical internal APIs for which supported replacements do not exist in JDK 8 and, further, deprecate those which have supported replacements in JDK 9 with the intent to encapsulate them, or possibly even remove them, in JDK 10.

...

Critical internal APIs for which replacements are introduced in JDK 9 will be deprecated in JDK 9 and either encapsulated or removed in JDK 10.

答案在链接文档中。 Spring 不直接依赖于 Unsafe,但 Spring 依赖于 Objenesis,而 Objenesis 依赖于 Unsafe.

Objenesis 对 Unsafe 的依赖性:https://github.com/easymock/objenesis/blob/master/main/src/main/java/org/objenesis/instantiator/sun/UnsafeFactoryInstantiator.java

Spring 对 Objenesis 的依赖本身就有点奇怪。 Spring 的构建脚本获取 Objenesis 二进制文件并使用 JarJar 工具进行字节码级别的更改。您可以在以下构建脚本中看到它的作用:https://github.com/spring-projects/spring-framework/blob/master/build.gradle(在撰写本文时,请参阅第 326-343 和 347 行)。

这实质上意味着 Spring 的 "spring-core" 二进制文件最终在 org.springframework.objenesis.* 包结构下包含了 类 的负载,但是那些 类 最初存储在 Objenesis GitHub 的源代码中,由 Objenesis 团队发布为二进制文件,在 Spring 的构建期间获取,重新打包为 org.springframework.* 包,然后作为一部分重新发布Spring。这就是您找不到它们的原因。

Spring 使用 Unsafe(通过 Objenesis)创建 类 而无需首先调用构造函数。