这几天在看dubbo的源码,看到里面有一个方法是检测类的重复加载的,感觉挺实用的,写下来,防备自己忘记
package com.test;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
public class VersionTest {
public void checkDuplicate(String path, boolean failOnError){
try {
// 在ClassPath搜文件
Enumeration<URL> urls = VersionTest.class.getClassLoader().getResources(path);
Set<String> files = new HashSet<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String file = url.getFile();
if (file != null && file.length() > 0) {
files.add(file);
}
}
}
// 如果有多个,就表示重复
if (files.size() > 1) {
String error = "Duplicate class " + path + " in " + files.size() + " jar " + files;
if (failOnError) {
throw new IllegalStateException(error);
} else {
System.out.println(error);
}
}
} catch (Throwable e) { // 防御性容错
e.printStackTrace();
}
}
//获取版本号
public static String getVersion(Class<?> cls, String defaultVersion) {
try {
// 首先查找MANIFEST.MF规范中的版本号
String version = cls.getPackage().getImplementationVersion();
if (version == null || version.length() == 0) {
version = cls.getPackage().getSpecificationVersion();
}
if (version == null || version.length() == 0) {
// 如果规范中没有版本号,基于jar包名获取版本号
CodeSource codeSource = cls.getProtectionDomain().getCodeSource();
if(codeSource == null) {
logger.info("No codeSource for class " + cls.getName() + " when getVersion, use default version " + defaultVersion);
}
else {
String file = codeSource.getLocation().getFile();
if (file != null && file.length() > 0 && file.endsWith(".jar")) {
file = file.substring(0, file.length() - 4);
int i = file.lastIndexOf('/');
if (i >= 0) {
file = file.substring(i + 1);
}
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
}
while (file.length() > 0 && ! Character.isDigit(file.charAt(0))) {
i = file.indexOf("-");
if (i >= 0) {
file = file.substring(i + 1);
} else {
break;
}
}
version = file;
}
}
}
// 返回版本号,如果为空返回缺省版本号
return version == null || version.length() == 0 ? defaultVersion : version;
} catch (Throwable e) { // 防御性容错
// 忽略异常,返回缺省版本号
logger.error("return default version, ignore exception " + e.getMessage(), e);
return defaultVersion;
}
}
public static void main(String[] args) {
new VersionTest().checkDuplicate("com/spring/schema/spring_schema/entity/People.class",false);
}
}
输出的结果为:
Duplicate class com/spring/schema/spring_schema/entity/People.class in 2 jar [file:/D:/workspacelianxi/spring-schema/src/spring-schema-0.0.1-SNAPSHOT.jar!/com/spring/schema/spring_schema/entity/People.class, /D:/workspacelianxi/spring-schema/target/classes/com/spring/schema/spring_schema/entity/People.class]