思路参考这个回答
在解决依赖冲突的场景中,偶尔会遇到这个问题:
1 | java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type taticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory; used in the signature |
显然,这是log4j的依赖冲突,但是通过idea的Mavendependency Analyzer并没有找到冲突的依赖,想办法排依赖可能就解决了。然而这种解决方式并不靠谱。这里把问题出现的原因和解决流程记录一下。
排查流程
这个问题是ILoggerFactory这个类被加载了两次
- 在jvm参数里添加 -verbose:class, 打印类的加载路径
找到冲突的jar包可以看到这个类在slf4j-api-1.7.30.jar和hive-exec-2.3.8.jar上都出现了,可以断定hive-exec-2.3.8.jar里包含了其他版本的slf4j依赖。1
2
3[Loaded org.slf4j.ILoggerFactory from file:/Users/kunni/.m2/repository/org/slf4j/slf4j-api/1.7.30/slf4j-api-1.7.30.jar]
......
[Loaded org.slf4j.ILoggerFactory from file:/Users/kunni/.m2/repository/org/apache/hive/hive-exec/2.3.8/hive-exec-2.3.8.jar] - 通过反编译查看依赖版本
通过jd-gui查看hive-exec-2.3.8.jar里包含的slf4j依赖版本
发现两个版本确实是不一致的,想办法解决这个问题。
解决
- 通过maven的依赖覆盖解决这个问题
- 通过maven shade插件改名解决这个问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.slf4j..</pattern>
<shadedPattern>shade.org.slf4j.</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>