ojdbc11.jar在Java 17下易冲突的根本原因是JPMS模块系统与驱动模块声明不匹配:其虽含module-info.java和automatic-module-name,但requires声明不全、反射受限(需--add-opens java.base/java.lang=ALL-UNNAMED)、且classpath混入旧版ojdbc会触发类加载器隔离导致LinkageError或ClassCastException。
根本原因不是驱动本身写得不好,而是 java 17 默认启用模块系统(jpms),而 ojdbc11.jar 虽然带 module-info.java、声明了 automatic-module-name: oracle.jdbc,但它和 jdk 自身模块(如 java.xml.bind)、其他依赖(如 hikaricp、spring boot)之间存在加载时序与反射限制的双重夹击。常见表现是:noclassdeffounderror: javax/sql/datasource、module not found: oracle.jdbc,或连接池初始化时卡在 drivermanager.getconnection() 不抛异常也不返回。
如果你的项目用了模块化(即存在 module-info.java),光靠 Maven 引入 ojdbc11 不够——编译期就报错 module not found: oracle.jdbc;绕过编译强行运行,DriverManager 会因类加载器隔离找不到驱动类,最终抛 SQLException: No suitable driver。
requires java.sql; 是基础,但必须额外加一行:requires oracle.jdbc;
requires transitive oracle.jdbc; —— ojdbc11 不导出任何第三方模块,且你代码通常只用 java.sql 接口module-info.java),这步可跳过,但需靠 JVM 参数补位ojdbc11 内部大量使用反射访问 java.base 和 java.sql 的私有字段(比如 socket 配置、SSL 上下文初始化),Java 17 默认禁止这种跨模块反射。HikariCP 尤其敏感,不加参数常卡在连接创建阶段,日志里既没错误也没成功记录。
--add-opens java.base/java.lang=ALL-UNNAMED
java.xml.bind(比如某些 XML 解析逻辑),还得加:--add-modules java.xml.bind
--add-modules ALL-SYSTEM —— 过度开放会掩盖真实依赖问题,且在生产环境可能被安全策略拦截最隐蔽也最常被忽略:Tomcat 或 WebLogic 自带 ojdbc6.jar 或 ojdbc7.jar,而你的 WAR 包里又打了 ojdbc11.jar。类加载器可能从容器路径先加载旧版,导致 OracleConnection 类版本不一致,运行时报 LinkageError 或 ClassCastException: oracle.jdbc.driver.T4CConnection cannot be cast to java.sql.Connection。
WEB-INF/weblogic.xml 中强制包级优先:<package-name>oracle.jdbc.*</package-name>
$CATALINA_HOME/lib/ojdbc*.jar(重命名即可,别删),这是最干净的做法mvn dependency:tree | grep ojdbc,确保只有一个 ojdbc11 出现在 compile/runtime scope真正麻烦的从来不是“连不上”,而是“看起来连上了,但某天批量插入突然超时”或者“本地跑得通,上预发就偶发 ClassCastException”——这些基本都指向驱动加载路径或模块边界没理清。别迷信最新版,先查清数据库版本和 JDK 运行时约束,再决定是用 ojdbc8 还是 ojdbc11。
立即学习“Java免费学习笔记(深入)”;