今天遇到了一个问题:
程序中某处报了ClassNoDefineError。这个类属于jna框架。检查jna的jar,发现确实没有那个类。关键在于这个报错是在一个依赖内部发生的,jna的jar是这个依赖的内部依赖,即当前应用的一个间接依赖。因为使用的jar是一个比较小众的服务,所以第一印象就是这个服务依赖的jna版本错了。进入到服务的pom看了后,发现该服务使用的jna版本是正确的,但是当前应用的jna版本却是错误的。
首先想到的是依赖冲突,使用如下命令检查了当前应用的全部依赖:
1 |
mvn dependency:tree |
检查后可以确认当前应用的依赖(包括间接依赖)中只有一个jna框架,可以排除依赖冲突的问题。
仔细思索了一会儿,猜测是spring框架的问题。
退到工程最外部的pom文件,找到了spring-boot-dependencies:
1 2 3 4 5 6 7 8 9 |
<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的版本变量:
1 |
<jna.version>4.5.2</jna.version> |
这个版本和应用的版本是一致的。随后在spring-boot-dependencies的dependencyManagement中找到了jna框架:
1 2 3 4 5 6 7 8 9 10 |
<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的影响,还是使用了一个早期的版本。
解决方式两个:
- 将jna框架也添加到dependencyManagement中;
- 先exclude掉jna间接依赖,再直接添加jna依赖并声明版本号
发表评论