今天遇到了一个问题:
程序中某处报了ClassNoDefineError。这个类属于jna框架。检查jna的jar,发现确实没有那个类。关键在于这个报错是在一个依赖内部发生的,jna的jar是这个依赖的内部依赖,即当前应用的一个间接依赖。因为使用的jar是一个比较小众的服务,所以第一印象就是这个服务依赖的jna版本错了。进入到服务的pom看了后,发现该服务使用的jna版本是正确的,但是当前应用的jna版本却是错误的。
首先想到的是依赖冲突,使用如下命令检查了当前应用的全部依赖:
mvn dependency:tree
检查后可以确认当前应用的依赖(包括间接依赖)中只有一个jna框架,可以排除依赖冲突的问题。
仔细思索了一会儿,猜测是spring框架的问题。
退到工程最外部的pom文件,找到了 spring-boot-dependencies :
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.9.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
检查 spring-boot-dependencies 的pom果然看到了jna的版本变量:
<jna.version>4.5.2</jna.version>
这个版本和应用的版本是一致的。随后在 spring-boot-dependencies 的dependencyManagement中找到了jna框架:
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>${jna.version}</version> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>${jna.version}</version> </dependency>
现在问题清晰了。问题出在maven的 dependencyManagement 上。
dependencyManagement的作用主要是依赖版本控制。其影响的范围包括:
在这个应用中, spring-boot-dependencies 是应用pom的 dependencyManagement 成员,因此 spring-boot-dependencies 自己的 dependencyManagement 成员也会传递生效。jna框架是应用通过一个依赖的间接依赖,虽然在这个依赖中指明了jna的版本号,但是受到 spring-boot-dependencies 的 dependencyManagement 的影响,还是使用了一个早期的版本。
解决方式两个: