You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JRE9上运行JDK8编译且依赖Unsafe的代码?

解决JDK8编译的Unsafe代码在JDK9运行时的NoSuchMethodError问题

首先,你遇到的问题其实和JDK9引入的**模块系统(Project Jigsaw)**密切相关——虽然sun.misc.Unsafe没有被移除,但它的访问规则、编译/运行时可见性发生了根本性变化,这就是你碰到兼容性问题的核心原因。

为什么会抛出NoSuchMethodError?

JDK9之后,sun.misc.Unsafe被归类到jdk.unsupported模块中,这个模块默认是不对外暴露内部包的。当你用JDK8编译的代码在JDK9上运行时,JVM虽然能找到Unsafe类,但模块系统会限制未命名模块(你的应用代码默认属于这类)访问它的方法,最终就出现了「方法明明存在却找不到」的NoSuchMethodError。

至于无法用JDK9重新编译的问题,是因为JDK9默认会严格限制对内部API(比如sun.misc下的类)的访问,编译器直接会报错说找不到sun.misc.Unsafe,或者不允许访问这类非标准API。

如何修复这个问题?

1. 让JDK9运行时允许访问Unsafe

如果只是想让JDK8编译好的代码在JDK9上跑起来,你需要给JVM添加启动参数,放开jdk.unsupported模块对未命名模块的sun.misc包访问:

java --add-exports jdk.unsupported/sun.misc=ALL-UNNAMED 你的主类名

这个参数的意思是:把jdk.unsupported模块下的sun.misc包,导出给所有未命名模块(也就是你的应用代码)。

2. 用JDK9重新编译代码

如果要在JDK9环境下重新编译依赖Unsafe的代码,需要同时给编译器添加参数,允许访问内部API:

javac --add-exports jdk.unsupported/sun.misc=ALL-UNNAMED 你的Java文件.java

编译完成后,运行时同样需要加上上面提到的--add-exports参数才能正常执行。

3. 长远的替代方案(推荐)

sun.misc.Unsafe本身是内部API,Oracle从未承诺过它的向后兼容性,JDK9之后的版本对它的限制只会越来越严格。如果可能的话,建议替换成标准API:

  • 内存操作场景:可以用java.nio.ByteBuffer(底层同样依赖Unsafe,但属于标准API,兼容性有保障)
  • 对象/字段操作场景:优先使用Java反射API,JDK11及以上版本可以用java.lang.invoke.VarHandle——这是官方推荐的Unsafe替代方案。

关于Java向后兼容性的误解

Java的向后兼容性承诺只覆盖标准API,内部API(比如sun.*、com.sun.*下的类)不在这个范围内。这类API随时可能被修改、隐藏甚至移除,依赖它们的代码在版本升级时很容易出问题——这也是Oracle一直强调不要使用内部API的原因。

你的测试类的解决方法

你的测试类依赖sun.misc.Unsafe,同样会遇到上述问题。按照下面的步骤操作就能正常运行:

  1. 编译测试类:
javac --add-exports jdk.unsupported/sun.misc=ALL-UNNAMED UnsafeTest.java
  1. 运行测试类:
java --add-exports jdk.unsupported/sun.misc=ALL-UNNAMED UnsafeTest

内容的提问来源于stack exchange,提问作者HPCS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:23:33