JAR conflict resolution

Today I ran into a friend in the group and asked that the online program seems to have multiple Netty packages of different versions. How do I see which one is loaded at the bottom?

JAR conflict resolution JAR conflict resolution

Before talking about how to look, let’s talk about it first, when you start to realize that there are multiple versions of Jar packages in the project, it is all because of these exceptions:

  • 1. java.lang.NoSuchMethodException: A method was called in my code because other versions of the jar are loaded, and this version just doesn't have this method.
  • 2. java.lang.NoClassDefFoundError: It is good when compiling, but when running, there is no such class because of the loaded jar version.
  • 3. java.lang.ClassNotFoundException: When a Class is dynamically loaded, the class cannot be found because the jar to be loaded is not the correct version.

When you run ok locally, but find these errors on the server, you must realize that it is likely to be a jar conflict (there are multiple versions of the same dependency). This problem often manifests itself in this way: when deploying multiple instances, some instances are good, while others are not.

View loaded classes and methods

According to the type of abnormality analyzed before, we can go to the operating site to confirm the current loading problem.

Here we can use Ali's open source Arthas tool. If you use it for the first time, please install it and then run it as follows:

-O curl https://arthas.aliyun.com/arthas-boot.jar 
java -jar arthas-boot.jar

After running, it will print out the currently running java application, such as:

[INFO] arthas-boot version: 3.4.6 
[INFO] Process 40611 already using port 3658 
[INFO] Process 40611 already using port 8563 
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. 
* [1]: 40611 chapter4-3-0.0.1-SNAPSHOT.jar 
  [2]: 37786

Select the java application you want to view by entering the number, for example, select here: 1, enter chapter4-3-0.0.1-SNAPSHOT.jar.

Here are two important commands :

The first one: sc command , let's confirm whether there is a corresponding class under the jar package that may conflict. Some different versions of packages have different classes, which can be distinguished right away.

For example, with the following command, we can check what classes are in the com.didispace package:

[arthas@40611]$ sc com.didispace.* 
com.didispace.chapter43.Chapter43Application 
com.didispace.chapter43.Chapter43Application$$EnhancerBySpringCGLIB$$8b82b194 
com.didispace.chapter43.UploadController 
Affect(row-cnt:3) cost in 6 ms.

The second one: sm command, to see which methods a specific class has. Some version differences are that a certain method has been removed. At this time, we can use this command to check.

For example, through the following command, let's check what methods are available under the com.didispace.chapter43.UploadController class:

[arthas@40611]$ sm com.didispace.chapter43.UploadController 
com.didispace.chapter43.UploadController ()V 
com.didispace.chapter43.UploadController create(Lorg/springframework/web/multipart/MultipartFile;)Ljava/lang/String; 
com.didispace.chapter43.UploadController uploadPage()Ljava/lang/String; 
Affect(row-cnt:3) cost in 5 ms. 

Find and resolve conflicts

After confirming that it is a loading error, we have to resolve the conflict. So what we have to do to resolve the conflict is to find out where the conflict is and what we want to remove or force

The method to find out the version conflict: Use the Maven command: mvn -U dependency:tree -Dverbose.

After the command is executed, all dependencies will be listed in the console in a tree form, and then the conflicting packages will be searched to see which dependencies are brought in (searching in IDEA will highlight and make it easier turn up).

[INFO] com.didispace:chapter4-3:jar:0.0.1-SNAPSHOT 
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.4.1:compile 
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.4.1:compile 
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.4.1:compile 
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.4.1:compile 
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.4.1:compile 
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile 
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile 
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.13.3:compile 
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.13.3:compile 
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.30:compile 
[INFO] | | + - jakarta.annotation: jakarta.annotation-api: jar: 1.3.5: compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.27:compile 
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.4.1:compile 
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.11.3:compile 
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.11.3:compile 
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.11.3:compile 
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.11.3:compile 
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.11.3:compile 
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.11.3:compile 
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.4.1:compile 
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.41:compile 
[INFO] |  |  +- org.glassfish:jakarta.el:jar:3.0.3:compile 
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.41:compile 
[INFO] |  +- org.springframework:spring-web:jar:5.3.2:compile 
[INFO] |  |  \- org.springframework:spring-beans:jar:5.3.2:compile 
[INFO] |  \- org.springframework:spring-webmvc:jar:5.3.2:compile 
[INFO] |     +- org.springframework:spring-aop:jar:5.3.2:compile 
[INFO] |     +- org.springframework:spring-context:jar:5.3.2:compile 
[INFO] |     \- org.springframework:spring-expression:jar:5.3.2:compile 
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.4.1:compile 
[INFO] |  +- org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile 
[INFO] |  |  +- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile 
[INFO] | | + - org.attoparser: attoparser: jar: 2.0.5.RELEASE: compile

There are two main ways to resolve version conflicts:

  • 1. After finding the unwanted version through the above command, use exclusions to exclude it among the imported dependencies
  • 2. Mandatory specify the version to be used in pom.xml, so that this has the highest priority and will not introduce the version that other versions will bring in.

Guess you like

Origin blog.csdn.net/yaxuan88521/article/details/113748857