import org.apache.commons.codec.binary.Hex;
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 错误。
public String encrype(String s) {
try {
MessageDigest sha256Digest = MessageDigest.getInstance("SHA-256");
String result = Hex.encodeHexString(sha256Digest.digest(s.getBytes(StandardCharsets.UTF_8)));
return Hex.encodeHexString(HmacUtils.getHmacSha256(result.getBytes()).doFinal(result.getBytes()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "error";
}
}
<dependencies>
<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 依赖调解,如果不调解行不行。
当使用 Maven 的过程中,如果同时引入了 groupId 和 artifactId 相同而 version 不同的包时,Maven 会认为发生了依赖冲突,将进行依赖调解,通过两个原则决定使用哪个版本的包:第一原则,路径最近者优先,如前文。如果路径相同,则使用第二原则,在 pom 中第一声明者优先。而当我们在点击 Run 运行时,classpath 中将只会有一个明确版本的包。
思考一下。Java 在运行时,是否能引入版本不同的包。其实这个问题是在问,java 命令的 classpath 参数中能不能有多个版本不同的包,当然是可以的。classpath 参数的是用于指示JVM如何搜索 class 文件,当你在 classpath 中指定的路径下有多个版本不同的包,JVM 都会去 jar 包下搜索 class 文件进行加载,而至于 class 能不能成功加载,则在于 ClassLoader 的逻辑,当同名类被加载时,则不会再被加载,即同一个类只会被加载一次。这也意味,当有多个版本不同的包时,包在 classpath 中的顺序,决定了哪个包中的类能先被加载。而这样具有不确定性。因为在生产环境下通常使用shell命令将 jar 包拼接:
LIB_DIR=lib
LIB_JARS=`ls $LIB_DIR|grep .jar|awk '{print "'$LIB_DIR'/"$0}'|tr "\n" ":"`
public class Main {
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) {
}
}
}
}
[arthas@32328]$ sc -d org.apache.commons.codec.digest.DigestUtils
class-info org.apache.commons.codec.digest.DigestUtils
code-source /D:/mavenrepo/commons-codec/commons-codec/1.6/commons-codec-1.6.jar
name org.apache.commons.codec.digest.DigestUtils
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name DigestUtils
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@58644d46
+-sun.misc.Launcher$ExtClassLoader@24e74ca5
classLoaderHash 58644d46
可以从 code-source 中清晰的查到 DigestUtils 是哪个包下的 Class,这时就该意识到发生了依赖冲突问题。
而通过 jad 命令,还能反编译,在线看代码。好用!
更多精彩推荐
☞倪光南、求伯君“出山”:爱解 Bug、无惧“35岁魔咒”、编码之路痛并快乐!
☞腾讯回应发布虚假广告被罚20万;苹果客服回应iPhone 12屏幕发绿;Chrome 87 正式版发布|极客头条点分享 点点赞 点在看