【复盘】bcprov-jdk16包冲突问题(不同版本jar兼容) 以及 maven-shade-plugin的使用

2年前 (2022) 程序员胖胖胖虎阿
357 0 0

背景概述

因为自己本身是做互联网金融业务,平时会对接比较多的银行,最近对接的一家给的加解密包,版本比较低导致在现有项目中不能使用,bcprov-jdk16-1.46.jar (12年的包),直接在现有项目中引入的话,直接报错。

Exception in thread "main" java.lang.IllegalAccessError: tried to access method
 org.bouncycastle.math.ec.ECPoint$Fp.<init>(Lorg/bouncycastle/math/ec/ECCurve;Lorg/bouncycastle/math/ec/ECFieldElement;
 Lorg/bouncycastle/math/ec/ECFieldElement;)V from class SM2Utils.SM2 at SM2Utils.
 SM2.<init>(SM2.java:51) at SM2Utils.SM2.Instance(SM2.java:36) at 
 SM2Utils.SM2SignUtils.sign(SM2SignUtils.java:120) at EncryptUtils.EncryptUtils.encryptText(EncryptUtils.java:22) at 

大概错误信息如下 非法的访问错误,尝试访问xxx.下的方法,失败了,仔细想下为什么,看了源码之后才发现原来项目中依赖传递直接使用的是高版本的bcprov包,所以导致低版本的jar不会被引入到其中。具体原因就是同一个jar中出现,包名+类名 在类加载的时候,因为双亲委派机制只会加载一次,而加载进来的正好是高版的的jar,并且高版本中不兼容低版本所以问题就出现。

画一个图如下,

【复盘】bcprov-jdk16包冲突问题(不同版本jar兼容) 以及 maven-shade-plugin的使用

解决方案1(尝试不同版本的jar)

所以可以看出来,解决办法,刚开始的时候是想办法通过bcprov包其他版本看是否可以兼容低版本的bcprov-jdk16-1.46版本。发现基本上都试了一下。都不可以使用。

解决方案2(手动升级jar)

https://qxlxi.blog.csdn.net/article/details/122419383
然后在同事的提示下说可以尝试将资方给的加解密包进行手动升级,新建一个项目,然后把依赖的bcprov-jdk16-1.46升级到bcprov-jdk15to18-1.68 版本,然后重新升级之后发现,加解密是没有问题的,验签的话出现问题,不能使用

解决方案3 (maven-shade-plugin)

既然重写资方的jar不能使用,那么有没有高低版本可以在项目中直接使用的相关配置呢,于是查到有这种方式。

https://segmentfault.com/a/1190000038382111 具体可以文章。

相关配置如下

<plugin>
      <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-shade-plugin</artifactId>
			 <version>3.2.1</version>
			 <configuration>
			 <createDependencyReducedPom>false</createDependencyReducedPom>
			 </configuration>
			 <executions>
				 <execution>
					 <!-- Maven 的生命周期 -->
					 <phase>package</phase>
					 <goals>
					 <!-- 插件目标 -->
					 <goal>shade</goal>
					 </goals>
		    <configuration>
				<!-- <minimizeJar>true</minimizeJar>-->
				 <!-- 配置多版本 jar 包中类路径的重命名
 					-->
			 <relocations>
				 <relocation>
					 <pattern>org.bouncycastle</pattern>
					 <shadedPattern>org.new.bouncycastle</shadedPattern>
				 </relocation>
			 </relocations>
			 <filters>
				 <filter>
					 <artifact>*:*</artifact>
				 <excludes>
				 <exclude>META-INF/*.SF</exclude>
				 <exclude>META-INF/*.DSA</exclude>
				 <exclude>META-INF/*.RSA</exclude>
				 </excludes>
				 </filter>
				 </filters>
 				</configuration>
		 </execution>
		</executions>
 </plugin>

配置如何设置为true的话,在maven私服不能打包。需要删除。

<dependency>-->
	<groupId>commons-codec</groupId>
	<artifactId>commons-codec</artifactId>
    <version>1.7</version>
    </dependency>
<dependency>
  <groupId>commons-httpclient</groupId>
  <artifactId>commons-httpclient</artifactId>
  <version>3.0.1</version>
  </dependency>

jar中还包含其他的包,直接打入项目中,发现对一些类会有冲突,还是因为类加载机制的原因,只会加载一个类。所以删除无用的包

重新打包,发现可以在测试环境和本地可以使用。

总结:

1.遇到问题不能慌张,需要慢慢分析出问题的来龙去脉,找到具体的原因。

2.jar冲突的问题,a.我们可以直接使用maven-helper进行直接jar冲突解决,但是对于高低版本不兼容的情况下,需要使用maven的插件进行解决。

具体的使用,https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html

https://blog.csdn.net/yangguosb/article/details/80619481

参考文章

1.https://blog.csdn.net/yangguosb/article/details/80619481
2.https://www.playpi.org/2019120101.html
3.https://maven.apache.org/plugins/maven-shade-plugin/
4.https://xie.infoq.cn/article/5a18670154051e26591e2090f

原理

既然通过重命名jar包可以同一个项目中加载相同的jar不同版本,具体是什么原理呢,将打的包进行javap -c 看到后就恍然大雾。
【复盘】bcprov-jdk16包冲突问题(不同版本jar兼容) 以及 maven-shade-plugin的使用
原来,在生成的.class字节码文件中编译,构建包的时候替换成了新的包名,所以记载的时候相同jar不同版本就可以加载了。比较神奇,牛。

相关文章

暂无评论

暂无评论...