Nacos 2.x.x版本不适用JDK17的处理方式

由于nacos使用了反射,但是高版本 JDK(Java9+)引入了Java 模块化机制(JPMS),做了严格的反射权限控制,而 Nacos 2.x.x 底层依赖的 Tomcat、SpringBoot 组件还沿用了 JDK8 的反射写法,在高版本 JDK 中会触发权限拦截,直接导致启动失败。

报错信息:Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field static final boolean java.io.FileSystem.useCanonCaches accessible: module java.base does not "opens java.io" to unnamed module @2f7a2457

解决方案包括:

方案一:降级 JDK 版本到 JDK8

最简单粗暴,但是如果已经使用了更高版本JDK切换比较麻烦则不推荐。

方案二:改用Nacos 3.X.X版本

Nacos 3.x.x 需要64 bit JDK 17+,新版本跟老版本有些区别,如果仅用于学习可以使用,生产上需要另外考虑适配性。

方案三:不改 JDK 版本,修改启动脚本添加兼容参数

以Nacos 2.5.2 的windows启动cmd文件为例,添加使用反射访问JDK的模块的权限的参数,效果如下:

在set NACOS_OPTS 前面,添加如下参数

bash 复制代码
rem ========== Java 17+ module opens for Tomcat 9.0.83+ ===============
set "JAVA_OPT=%JAVA_OPT% --add-opens java.base/java.io=ALL-UNNAMED"
set "JAVA_OPT=%JAVA_OPT% --add-opens java.base/java.lang=ALL-UNNAMED"
set "JAVA_OPT=%JAVA_OPT% --add-opens java.base/java.util=ALL-UNNAMED"
set "JAVA_OPT=%JAVA_OPT% --add-opens java.base/sun.nio.ch=ALL-UNNAMED"
rem ====================================================================

在最后的启动命令里,添加上刚刚添加的参数,在"%JAVA%"后面添加%JAVA_OPT%,不用添加双引号 。

bash 复制代码
set COMMAND="%JAVA%" %JAVA_OPT% %NACOS_JVM_OPTS% %NACOS_OPTS% %NACOS_CONFIG_OPTS% %NACOS_LOG4J_OPTS% nacos.nacos %*

保存后正常启动即可。其他版本的启动文件可能略有区别,视情况修改。

前面加的--add-opens 是JVM 核心参数,作用是「开放模块权限 」,允许指定模块的指定包,对「未命名模块」开放反射访问权限(包括私有字段 / 私有方法)

ALL-UNNAMED :代表「所有未命名模块」,Nacos、Tomcat、SpringBoot 这些应用程序,在 JDK 模块化体系中都属于「未命名模块」,写死这个值即可。

相关推荐
张柏慈1 天前
Java性能优化:实战技巧与案例解析
java
天“码”行空1 天前
简化Lambda——方法引用
java·开发语言
带刺的坐椅1 天前
MCP 进化:让静态 Tool 进化为具备“上下文感知”的远程 Skills
java·ai·llm·agent·solon·mcp·tool-call·skills
java1234_小锋1 天前
Java线程之间是如何通信的?
java·开发语言
张张努力变强1 天前
C++ Date日期类的设计与实现全解析
java·开发语言·c++·算法
while(1){yan}1 天前
Spring事务
java·数据库·spring boot·后端·java-ee·mybatis
毕设源码-赖学姐1 天前
【开题答辩全过程】以 高校社团管理平台为例,包含答辩的问题和答案
java
余瑜鱼鱼鱼1 天前
线程和进程的区别和联系
java·开发语言·jvm
小唐同学爱学习1 天前
如何解决海量数据存储
java·数据库·spring boot·mysql