检测类路径下是否存在jar包中的class冲突,通常用于web应用的lib目录下class冲突检查
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
This comment has been minimized.
用于检测多个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]