从Java 1.8迁移至Java 17时sun.security.action包不可见问题咨询
Java 8 迁移 Java 17 构建报错
package sun.security.action is not visible 排查解决指南 问题根因
Java 9 引入JPMS模块化系统后,对sun.*开头的JDK内部API做了强封装限制。sun.security.action属于java.base模块的内部包,默认不会向未命名模块(即传统classpath模式加载的非模块化项目)导出,Java 8阶段无模块化限制可以直接访问,升级到Java17后就会触发该可见性报错。
排查步骤
先定位所有引用sun.security.action包的代码位置:
- 业务代码直接引用:全局搜索项目源码的import语句,确认自己代码里的调用点
- 第三方依赖引用:Maven项目执行
mvn dependency:tree、Gradle项目执行gradle dependencies,结合编译报错的类名定位到具体引入该内部API的第三方依赖版本
解决方案(按推荐优先级排序)
方案1:替换为JDK标准公开API(长期最优方案)
绝大多数场景下对sun.security.action的引用都是使用了其下的GetPropertyAction、LoadLibraryAction工具类,均可以用JDK公开API平替,无后续版本兼容风险:- 替换
GetPropertyAction:用java.security.PrivilegedAction函数式接口配合公开的System.getProperty实现,代码示例:// 旧Java 8写法(依赖内部API) import sun.security.action.GetPropertyAction; String config = AccessController.doPrivileged(new GetPropertyAction("app.config.path")); // Java17兼容写法(使用公开API) import java.security.PrivilegedAction; String config = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("app.config.path")); - 替换
LoadLibraryAction:将类库加载逻辑迁移到java.lang.ClassLoader公开的loadLibrary方法,放入特权块执行即可。
- 替换
方案2:升级适配Java17的第三方依赖版本
如果是第三方依赖引入的内部API调用,优先将对应依赖升级到2021年之后发布的、正式适配Java17的版本。常见触发该问题的依赖包括旧版本ASM、旧版本BouncyCastle加密库、老版本Java诊断工具包等,升级后均已完成内部API替换,不会再触发该报错。方案3:临时添加导出参数做过渡兼容(不推荐长期使用)
如果短时间内无法完成代码改造或依赖升级,可以通过添加JVM参数强制开放对应内部包,临时绕过编译/运行报错:- 编译阶段:给Maven编译插件、Gradle Java编译任务添加编译参数:
--add-exports java.base/sun.security.action=ALL-UNNAMED - 运行阶段:应用启动时在JVM启动参数中追加上述配置即可。
注意:该方案仅为过渡手段,后续JDK版本可能进一步收紧内部API访问权限,存在版本升级失效风险,不建议作为长期解决方案。
- 编译阶段:给Maven编译插件、Gradle Java编译任务添加编译参数:
内容的提问来源于stack exchange,提问作者man
相关产品推荐
相关产品推荐

