Java EE和CORBA模块在JDK 11中被彻底移除,包括java.xml.bind、java.corba、java.transaction等,需改用Jakarta EE第三方依赖替代。

Java EE 和 CORBA 模块被彻底移除
JDK 11 已开始模块化拆分,但真正“一刀切”移除 java.xml.bind、java.corba、java.transaction 等模块是在 JDK 17(基于 JEP 390 和 JEP 403)。如果你的项目还显式依赖 javax.xml.bind.JAXBContext 或 javax.transaction.UserTransaction,编译时会直接报 package javax.xml.bind does not exist。
解决办法不是降级,而是补依赖:
- 对 JAXB:添加 Maven 依赖
jakarta.xml.bind:jakarta.xml.bind-api+org.glassfish.jaxb:runtime - 对 JTA:改用
jakarta.transaction:jakarta.transaction-api - 避免反射调用
com.sun.xml.internal.*,这类内部实现 JDK 17 已强封装,--add-opens仅是临时绕过,不能作为长期方案
反射访问内部 API 被默认拒绝
JDK 17 启用强封装(JEP 403),所有 sun.*、jdk.internal.* 包默认不可反射访问。老项目里常见的 sun.misc.Unsafe、sun.nio.ch.DirectBuffer、jdk.internal.ref.Cleaner 调用,运行时会抛 java.lang.reflect.InaccessibleObjectException。
这不是编译期错误,容易漏测:
- 检查日志中是否出现
InaccessibleObjectException,尤其在对象序列化、NIO 缓冲区操作、或某些 ORM 框架初始化阶段 - 临时调试可加 JVM 参数:
--add-opens java.base/jdk.internal.ref=ALL-UNNAMED(按需放开,勿全开) - 长期必须替换:比如用
java.lang.ref.Cleaner替代jdk.internal.ref.Cleaner,用java.nio.ByteBuffer.allocateDirect()+Cleaner管理释放
Maven/Gradle 构建工具版本不兼容
不是 JDK 17 本身的问题,而是构建工具对新字节码版本和模块系统的支持滞后。常见现象:
- Maven 3.6.3 及更早版本无法识别 JDK 17 的
release参数,编译时报Unknown option: --release - Gradle 6.8 以下版本默认生成 Java 11 字节码,即使
sourceCompatibility = JavaVersion.VERSION_17也无效 - 某些插件(如
maven-compiler-plugin)若未声明<release>17</release>,可能意外编译出高版本字节码,导致部署到旧 JDK 报UnsupportedClassVersionError
建议组合:
- Maven ≥ 3.8.1 +
maven-compiler-plugin≥ 3.10.1 - Gradle ≥ 7.3(原生支持 Java 17)
- 始终显式配置
<release>17</release>或javac --release 17,避免依赖bootclasspath
ZGC 默认启用但需确认容器内存限制
JDK 17 中 ZGC 是生产就绪状态,且在 Linux 上默认启用(当堆 ≥ 256MB)。但很多团队升级后没注意它和容器环境的交互:
- 在 Docker/K8s 中,ZGC 会读取
/sys/fs/cgroup/memory.max判断可用内存;若镜像基础是openjdk:17-jre-slim但未设memory.limit_in_bytes,ZGC 可能误判为“无限内存”,触发频繁并发周期 - 使用
openjdk:17-jdk-alpine时,Alpine 的 musl libc 与 ZGC 的线程栈管理存在已知兼容问题(JDK-8279084),可能导致随机崩溃 - 若应用堆 ≤ 4GB,G1GC 仍是更稳选择;ZGC 真正优势在 ≥ 16GB 堆 + 亚毫秒停顿要求场景
上线前务必验证 GC 日志:-Xlog:gc*,gc+heap=debug:file=gc.log:time,tags,level,观察是否出现 ZUncommit 频繁抖动或 G1ConcRefinement 卡顿。
最常被忽略的一点:JDK 17 的 String::stripIndent 和 String::translateEscapes 行为与 JDK 11 的第三方库(如 Apache Commons Text)有语义冲突,如果项目同时用了这些工具类又没做排他控制,文本处理结果可能静默错位——这种问题不会报错,只会在特定输入下产生脏数据。


















