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

JDK8编译代码运行在OpenJDK17时Tomcat启动报SunJCE访问错误如何解决?

问题根因说明

你此前在maven-compiler-plugin中添加的--add-exports参数仅作用于编译阶段,Java 9+引入的模块系统访问限制在运行阶段仍然生效,因此启动时依旧触发访问异常。


可行解决方案

方案1:添加运行时JVM参数(临时兼容方案)

你需要在Tomcat的JVM启动参数中添加相同的导出规则,根据部署场景操作如下:

  • IDE本地启动Tomcat:打开Tomcat运行配置,在VM选项/VM arguments栏添加参数:
    --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED
  • Linux服务器部署Tomcat:编辑bin/catalina.sh文件,在文件开头添加配置:
JAVA_OPTS="$JAVA_OPTS --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED"
  • Windows服务器部署Tomcat:编辑bin/catalina.bat文件,在文件开头添加配置:
set JAVA_OPTS=%JAVA_OPTS% --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED

修改后重启Tomcat即可解决运行时报错问题。

方案2:优化代码避免访问JDK内部API(推荐治本方案)

com.sun.crypto.provider.SunJCE属于JDK内部非公开API,本身就不推荐直接引用,你可以通过以下方式避免直接实例化该类,完全避开模块访问限制:

// 先判断SunJCE是否已经注册,未注册再动态添加
Provider sunJceProvider = Security.getProvider("SunJCE");
if (sunJceProvider == null) {
    // Oracle/OpenJDK默认都会内置该Provider,仅特殊场景需要手动注册
    sunJceProvider = (Provider) Class.forName("com.sun.crypto.provider.SunJCE").newInstance();
    Security.addProvider(sunJceProvider);
}

该方案无需修改任何编译、运行参数,也兼容JDK 8到JDK 17+所有版本,不会受后续JDK版本升级影响。

方案3:反射绕过访问限制(仅当无法修改JVM参数、也无法重构代码时使用)

如果业务代码无法重构,也没有权限修改Tomcat启动参数,可以通过反射关闭构造方法的访问检查来实例化:

Class<?> sunJceClazz = Class.forName("com.sun.crypto.provider.SunJCE");
Constructor<?> constructor = sunJceClazz.getDeclaredConstructor();
constructor.setAccessible(true);
Provider sunJceProvider = (Provider) constructor.newInstance();
Security.addProvider(sunJceProvider);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:24:02