Maven 包冲突导致 NoSuchMethodError

项目清况

项目中有两个包都引用了jackson 的包且都是不再更新的版本

javascript 复制代码
// jarA 包中引入 org.codehaus.jackson 包 1.8.4 版本
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.8.4</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.8.4</version>
</dependency>

//jar B 包中引入了 org.codehaus.jackson 包 1.9.13 版本
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

//  org.codehaus.jackson  包最后在 2013 年的时候发生了组织变化(fastxml) ,且后续不再维护
// 如今正确使用jackson   应该引入以下的 3 个包:
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.17.1</version>
</dependency>

从上面包中看得出,项目有些年代感了(springmvc 3.x 的版本,打包成war 部署运行),本着能运行的情况下,绝不随意改动的原则,还是继续使用 org.codehaus.jackson 这个包

报错、异常

web 项目 能正常编译,运行时也正常启动,但执行到需要调用 org.codehaus.jackson 包中的某个方法时,产生运行异常:NoSuchMethodError:org.codehaus.jackson.map.ObjectMapper.setSerializationInclusion

找到报错处是 jarB 中的程序片段异常,找到对应代码中引用的包,定位后发现确实不存在这个方法,此时打开的是 1.8.4 的版本,(jarB 需要 1.9.13 版本的包)

处理冲突

找到问题了就好说,1.9与 1.8的版本应该上线兼容,则采用 1.9 的版本即可, 那么我们只需要在 jarA 中排除掉 1.8.4 的jackson 应该就能解决问题

xml 复制代码
<dependency>
    <groupId>org.china.xxxx</groupId>
    <artifactId>jarA</artifactId>
    <version>x.x.x</version>
    // 排除 ,jarA 中对低版本的引入
    <exclusion>
					<artifactId>jackson-core-asl</artifactId>
					<groupId>org.codehaus.jackson</groupId>
				</exclusion>
				<exclusion>
					<artifactId>jackson-mapper-asl</artifactId>
					<groupId>org.codehaus.jackson</groupId>
				</exclusion>
</dependency>

做了这个动作之后发现,项目中的已换成 1.9.13 版本

可以 使用 Maven Helper 工具来查看依赖冲突,exclude 包等

排除后充新编译项目启动运行,发现仍然

NoSuchMethodError:org.codehaus.jackson.map.ObjectMapper.setSerializationInclusion

进一步探究

  1. 编写单元测试 方法调用,发现单元测试没问题

📖 说明问题出在 Tomcat, 编译没问题说明包引入正常(idea 中包依赖显示正常,且跟踪代码也能找到正确的包) 问题应该出在 ClassLoad → 类加在上

  1. tomcat 启动项 增加 -XX:+TraceClassLoading -XX:+TraceClassUnloading tomcat 启动后发现,jackson 仍然加载 1.8.4 的版本
  1. 根据步骤 2 查看对应的目录发现,存在多个版本的包(但低版本的我应该排除掉了才对), 这个目录在 idea 项目的 target目录下 target/项目名称/WEB-INF/lib

结合了解到tomcat 加载 lib 目录下的包时,会按照顺序加在,且同样的包只会加在一次,所以,这里应该是优先加在了 1.8.4 所以后续引入的 1.9 就被忽略

那么问题来了-》 dependency 中 exclusion 排除了 低版本的包,是怎么又出现在 lib 中的,

发现问题

最后仔细观察 发现 jarA 是作为父项目,引入到当前项目中的

overlay 的资源会被覆盖到当前项目中,包括,WEB-INF 下的所有lib 这也是为什么在 lib 目录下仍然存在 1.8.4 版本的包. 需要在 overlay 中也将相应的包剔除

xml 复制代码
...
<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.2</version>
					<configuration>
						<overlays>
							<overlay>
								<groupId>com.unionman</groupId>
								<artifactId>unionmanframe</artifactId>
								<excludes>
									<exclude>**/jackson-core-asl-1.8.4.jar</exclude>
									<exclude>**/jackson-mapper-asl-1.8.4.jar</exclude>
								</excludes>
							</overlay>
						</overlays>
					</configuration>
	</plugin>
	...

最后再次启动,类正常加载 jackson-1.9.13 包

相关推荐
MyY_DO9 小时前
maven mysql jdk nvm node npm 环境安装
java·mysql·maven
kongxx2 天前
Maven运行任何命令都报错“Internal error: java.lang.ArrayIndexOutOfBoundsException”
java·开发语言·maven
tingting01192 天前
私有包上传maven私有仓库nexus-2.9.2
java·maven
ccmedu3 天前
Mac cursor设置jdk、Maven版本
jdk·maven·cursor
萌新小码农‍3 天前
回顾Maven
java·maven
倾城璧3 天前
Maven的单元测试
java·单元测试·maven
Pegasus丶百战3 天前
Cannot resolve symbol ‘XXX‘ Maven 依赖问题的解决过程
java·maven
萌新小码农‍3 天前
回顾:Maven的环境搭建
java·maven
码农研究僧4 天前
IDEA 中 Maven 依赖变灰并带斜线的解决方法及原理分析
java·maven·intellij-idea·pom依赖包
Suwg2094 天前
【由浅入深认识Maven】第3部分 maven多模块管理
java·前端·maven