Java类加载冲突本质是同名类被不同ClassLoader加载或类未进入classpath,需据报错类型(ClassNotFoundException/NoClassDefFoundError/LinkageError)精准定位根因,再通过dependency:tree、-verbose:class、jar -tf等手段验证类来源,按Web应用、多模块、多版本共存等场景选用provided、enforcer-plugin、自定义ClassLoader或shading等方案。

Java 类加载冲突不是名字撞了那么简单,而是 JVM 在运行时发现“同名类被不同方式加载”,或“该加载的类根本没进 classpath”,从而触发 ClassNotFoundException、NoClassDefFoundError、LinkageError 甚至 ClassCastException。解决的关键不在改代码,而在看清“类从哪来、被谁加载、有没有被跳过”。
先确认是不是真有冲突
别急着改包名或排除依赖,先验证问题本质:
- 看报错类型:是
ClassNotFoundException(压根找不到类)?还是NoClassDefFoundError(编译时有,运行时缺依赖)?或是LinkageError: loader constraint violation(两个 ClassLoader 各自加载了同一个类)?每种对应不同根因 - 检查是否只在特定环境出问题:本地 IDE 跑得通,但
java -jar报错 → 很可能是 fat jar 没打全,或依赖 scope 写成了provided - 新增某个依赖后立刻出问题 → 90% 是传递依赖引入了不兼容版本,比如新 SDK 带了 okio 3.x,而老模块依赖的 okhttp 3.x 只认 okio 1.x
查清楚类到底来自哪个 jar
目标是回答:“我要用的 com.fasterxml.jackson.databind.ObjectMapper,实际加载的是哪个 jar 里的?”
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 构建期查依赖树:
mvn dependency:tree -Dverbose | grep jackson-databind,留意是否有omitted for conflict或多个版本并存 - 运行时看真实加载:启动加
-verbose:class,再用grep ObjectMapper过滤,输出类似[Loaded com.fasterxml.jackson.databind.ObjectMapper from file:/xxx/jackson-databind-2.15.2.jar] - 检查打包结果:对生成的 jar 执行
jar -tf your-app.jar | grep ObjectMapper,确认类文件是否真的在里面;若没找到,说明 shade 插件没配或 scope 不对
按场景选解法,不硬套模板
没有万能方案,要根据部署方式和权限决定:
- Web 应用(Tomcat/Jetty):把
servlet-api.jar、log4j-api.jar这类容器已提供的库,scope 改成provided,避免应用包里重复打包 - Maven 多模块项目:在父 pom 用
maven-enforcer-plugin锁定关键依赖版本,比如强制所有模块用slf4j-api:2.0.7 - 必须共存多版本(如 POI 3.x 和 5.x):不能只靠排除,得用自定义
URLClassLoader隔离加载路径,新版 jar 用maven-shade-plugin重定位内部包(如把org.apache.poi改成shaded.org.apache.poi) - IDE 启动正常但命令行失败:检查 IDEA 的 “Build and run using” 和 “Run tests using” 是否都设为 Maven,而不是默认的 IntelliJ IDEA Runner(它会忽略 pom 中的 scope 和插件配置)
预防比修复更重要
日常开发中几个低成本习惯能大幅降低冲突概率:
- 所有第三方依赖统一在父 pom 声明
,子模块只写 groupId 和 artifactId,不写 version - 引入新 SDK 时,顺手跑一次
mvn dependency:tree -Dincludes=group:artifact,看看它带了哪些“隐形依赖” - 包名严格遵循反向域名规范(如
com.yourcompany.infra.util),不图省事写util或common - 团队约定:禁止在
src/main/resources下手动放 jar,所有依赖走 Maven 管理;确实需要隔离的库,走 shaded + relocation 流程
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










