Maven依赖冲突经历 Encryptor 类,主要是使用了DigestUtils 、MessageDigest 、HmacUtils 等类对字符串进行加密(下面代码是随便写的,只表示使用到了这些类),如下:import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.HmacUtils; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class Encryptor { public String encrype(String s) { MessageDigest sha256Digest = DigestUtils.getSha256Digest(); String result = Hex.encodeHexString(sha256Digest.digest(s.getBytes(StandardCharsets.UTF_8))); return Hex.encodeHexString(HmacUtils.getHmacSha256(result.getBytes()).doFinal(result.getBytes())); } public static void main(String[] args) { Encryptor encryptor = new Encryptor(); String s = 'test'; String result = encryptor.encrype(s); System.out.println(result); } /** output: fdd04dcac94e9803a72e4268141f773e2024a8fe46ba19a263be22c5ca83e931 **/ } IllegalAccessError 错误。Encryptor 时,发生了IllegalAccessError 报错。根据图中的具体报错信息,是说没有权限访问getSha256Digest 方法,我Ctrl+B点进getSha256Digest 方法查看,如下:getSha256Digest 方法是public 的访问级别,我一脸懵。由于这个方法很简单,既然报错,那我就索性不用了,换成下面这种写法。
ClassNotFoundException ,HmacUtils 这个类找不到。可是我Ctrl+B进去,这个类好好的就在那里啊。这时我才把注意力集中在思考是不是发生了Maven依赖冲突。我打开pom.xml,用Dependency Analyzer查看,果然我使用的commons-codec 包发生了冲突。commons-codec 包有两个版本1.6和1.10,所以Maven会进行依赖调解,第一原则是“路径最短者优先”,自然只会使用1.6版本的包。而我再去查看1.6的包下,getSha256Digest 方法是private 的访问级别,HmacUtils 这个类也不存在。解释了之前的报错。解决该冲突,通过排除依赖便能解决了,将A包下的commons-codec 排除,如下:<dependency> <groupId>com.chaycao.maven.dependency</groupId> <artifactId>A</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <artifactId>commons-codec</artifactId> <groupId>commons-codec</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.chaycao.maven.dependency</groupId> <artifactId>Y</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> 为什么需要Maven依赖调解 NoClassDefFoundError 、NoSuchMethodException 、IllegalAccessError 等错误。虽然Y模块在编译时,由于引入了commons-codec 1.10 能正常编译,但是在运行时,由于依赖冲突,只加载了1.6版本的包,所以不能正常运行。
shell 命令将jar包拼接:
排查在线问题的利器-Arthas IllegalAccessError 报错时,可以通过Arthas直接查看运行情况下的DigestUtils 。我们把代码变为最初的情况,且在Main类中加个死循环,为了让程序不死掉,以通过Arthas观察。public static void main(String[] args) { while (true) { try { Encryptor encryptor = new Encryptor(); String s = '1234567890'; String result = encryptor.encrype(s); System.out.println(result); } catch (Throwable e) { } } } } sc 命令查看DigestUtils :
code-source 中清晰的查到DigestUtils 是哪个包下的Class,这时就该意识到发生了依赖冲突问题。jad 命令,还能反编译,在线看代码。好用!参考
|
|