一、NoClassDefFoundError
该错误是在运行时抛出,出现在Tomcat启动时,场景有:
1、运行时A.class中调用了B.class,但是B.class不存在,此时就会抛出NoClassDefFoundError;
2、加载的类初始化错误 加载的class在初始化(loaded->linked->initialized)过程中出错了,初始化过程不可逆,以后凡是使用该class的地方都会抛出NoClassDefFoundError。这个错误通常是发生在clinit方法中,具体可能是静态变量,静态代码块。通常错误堆栈表现为:
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class xxxx
package com;
/**
* @author xiude
* @date 2018/5/20
*/
public class NoClassDefDemo {
public static void main(String[] args) throws InterruptedException {
for(int i = 1; i <= 3; i++) {
System.err.println("Time: " + i);
try {
System.err.println(CantInitClass.a); // try init class
} catch (Throwable t) {
t.printStackTrace();
}
Thread.sleep(100L);
}
}
private static class CantInitClass{
public static int a = 1;
static {
//如果try-catch,CantInitClass能初始化成功
//try{
// a = 1/0;
//}catch (Exception e){
//
//}
//除零出错导致CantInitClass没有被加载到classloader
a = 1/0;
}
}
}
二、ClassNotFoundException
该错误是在运行时抛出,启动时找不到类导致的。排查思路:
1、查询是否存在jar冲突
#!/bin/bash
for file in *.jar; do
grepResult=`/opt/taobao/java/bin/jar tvf $file | grep $2`;
if [ -n "$grepResult" ]; then
echo $file;
echo -e " * "$grepResult"\n";
fi
done
--使用方式(查找当前目录下):findClassInJar.sh . com/alibaba/common/logging/Logger
如果出现不同版本的jar,排除掉错误的那个。
综合第一、二点 的排查案例:
- step1: 该类所使用的子module是否引入了jar包?
- step2: 该类在该jar包中是否存在?
- step3: 是否存在该类所在的jar包发生版本冲突?
- step4: 该类中是否存在静态变量或静态代码块初始化失败?
三、NoSuchMethodError
这种错误一般是由于类加载冲突导致,引用了不匹配的类版本。
排查思路:
1、在JVM启动参数里添加-XX:+TraceClassLoading,启动时会打印出Loading class信息(工程太大会打爆日志的)
2、使用mvn dependency:tree -Dverbose -Dincludes=groupId:artifactId 打印怀疑加载有问题的jar
3、排除冲突的jar:<exclusion>或者直接在主pom中指定正确版本
4、
grep -rl 'org.apache.commons.collections4.CollectionUtils' /home/admin/usa-console/target/usa-console/BOOT-INF/lib
查看该目录下哪些jar里包含了CollectionUtils
参考:https://www.jianshu.com/p/100439269148