Last active
October 17, 2018 06:50
-
-
Save 0532/aacd9b60bcbde7d26098 to your computer and use it in GitHub Desktop.
检测类路径下是否存在jar包中的class冲突,通常用于web应用的lib目录下class冲突检查
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package liq.utils; | |
import java.io.File; | |
import java.util.Arrays; | |
import java.util.Enumeration; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.jar.JarEntry; | |
import java.util.jar.JarFile; | |
/** | |
* 检测classPath下的类冲突,通常用于web应用的lib目录下jar包中class冲突检测, | |
* 避免程序运行过程中出现如下的类似异常: | |
* {@link NoSuchMethodError}、{@link NoSuchMethodException} | |
* {@link ClassNotFoundException}、{@link NoClassDefFoundError} | |
* | |
* @author 0532 | |
* | |
*/ | |
public class ClassConflictCheck { | |
private static Map<String, HashSet<String>> classMap = new HashMap<String, HashSet<String>>(); | |
public static void check(String classPath) throws Exception { | |
File dir = new File(classPath); | |
File[] jarFiles = dir.listFiles(); | |
for (File jarFile : jarFiles) { | |
if (jarFile.getName().endsWith(".jar")) { | |
JarFile jar = new JarFile(jarFile); | |
Enumeration<JarEntry> enumeration = jar.entries(); | |
while (enumeration.hasMoreElements()) { | |
JarEntry jarEntry = enumeration.nextElement(); | |
if (jarEntry.getName().endsWith(".class")) { | |
storeClassAndJarRel(jarEntry.getName(), jar.getName()); | |
} | |
} | |
} | |
} | |
} | |
private static void storeClassAndJarRel(String className, String jarName) { | |
HashSet<String> jarSet = classMap.get(className); | |
if (jarSet == null) { | |
jarSet = new HashSet<String>(); | |
} | |
jarSet.add(jarName.substring(jarName.lastIndexOf("/") + 1)); | |
classMap.put(className, jarSet); | |
} | |
public static void main(String[] args) throws Exception { | |
//args = new String[] { "/Users/soft/tomcat-7.0.54.1/deploy/cloud-mobile-cloudapi-gateway/WEB-INF/lib" }; | |
for (String arg : args) { | |
check(arg); | |
} | |
boolean isConflict = false; | |
for (Iterator<Map.Entry<String, HashSet<String>>> iterator = classMap.entrySet().iterator(); iterator | |
.hasNext();) { | |
Map.Entry<String, HashSet<String>> entry = iterator.next(); | |
HashSet<String> jarSet = entry.getValue(); | |
if (jarSet.size() > 1) { | |
if (!isConflict) { | |
isConflict = true; | |
} | |
List<String> jarList = Arrays.asList(jarSet.toArray(new String[] {})); | |
System.out.println("Class conflict!!! the class :" + entry.getKey() | |
+ " has been duplicate inclusioned in the jars : " + jarList); | |
} | |
} | |
if(!isConflict) { | |
System.out.println("oh,good! there are no class conflict in the jars"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
用于检测多个Jar包冲突的class
当一个项目使用的jar包较多时,代码经常在运行的时候抛出异常:java.lang.NoSuchMethodException,java.lang.ClassNotFoundException,基本是存在多个jar包包含相同的class类文件导致的,运行期引用的class由于版本没对上导致没有该方法等
该小工具可以帮助你检测出classpath下,通常是项目的lib目录下是否存在类冲突,且告诉你冲突的jar包,方便定位处理。
使用说明,示例:
cd liq/util
javac ClassConflictCheck.java
java ClassConflictCheck xxx/WEB-INF/lib
如果没有任何类冲突,则输出: "oh,good! there are no class conflict in the jars"
否则则有类似如下的冲突输出 (两处冲突了):
Class conflict!!! the class :org/aspectj/weaver/tools/MatchingContext.class has been duplicate inclusioned in the jars : [aspectjweaver-1.6.6.jar, eclipse.aspectj__aspectjweaver-1.5.2a.jar-0.0.0.jar, aspectjtools-1.6.2.jar, aspectjweaver-1.6.2.jar]
Class conflict!!! the class :org/apache/batik/css/engine/value/css2/FontSizeAdjustManager.class has been duplicate inclusioned in the jars : [xml.xmlgraphics-1.7.jar, xml.xmlgraphics__batik-css-1.7.jar-1.7.jar]