java中如何判斷類的重複載入
阿新 • • 發佈:2018-12-26
這幾天在看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]