记一次NoClassDefFoundError
前言
今天跑新项目,发现新项目中的某个接口报NoClassDefFoundError
,该接口调用了某个类的静态方法,而该静态方法的主要作用是获取远程配置信息;错误信息是:java.lang.NoClassDefFoundError: Could not initialize class 某类
;第一眼发现这个错误还以为是这个类没导入,但是在编译文件下找到了该文件是存在的;
解决
- 通过参考中的几篇的文章中,发现是静态方法中的某个问题,获取远程配置,但是远程并没有配置;最后在配置中心进行配置就可以了;
- 可以将静态加载进行判断,不出错就行了;
例子
1
public class TestNoClassDefFoundError {
public static void main(String[] args) throws InterruptedException {
TestNoClassDefFoundError sample = new TestNoClassDefFoundError();
sample.getClassWithInitErrors();
}
private void getClassWithInitErrors() throws InterruptedException {
System.out.println("第一次new");
Thread.sleep(500);
try {
//第一次new ClassWithInitErrors类,JVM会加载该类,初始化该类的静态变量或执行静态块
new ClassWithInitErrors();
} catch (Throwable t) {
//因为初始化静态变量失败,所以加载类失败。
t.printStackTrace();
}
Thread.sleep(500);
System.out.println("-----------------------------------------------------");
System.out.println("第二次new");
Thread.sleep(500);
try {
//第二次new ClassWithInitErrors类,JVM不会再加载该类,而是抛出NoClassDefFoundError异常
new ClassWithInitErrors();
} catch (Throwable t) {
t.printStackTrace();
}
Thread.sleep(500);
System.out.println("-----------------------------------------------------");
System.out.println("第三次new");
Thread.sleep(500);
try {
//第三次new ClassWithInitErrors类,JVM不会再加载该类,而是抛出NoClassDefFoundError异常
new ClassWithInitErrors();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
class ClassWithInitErrors {
static int data = 1 / 0;
}
2
项目中大概就是这样的情况
public class MapUtil {
private static Map<String,String> keyMap;
static {
keyMap.put("1","2");
}
static void reload(){
keyMap=new HashMap<>();
}
public static String get(String key){
if(keyMap==null){
reload();
}
return keyMap.get(key);
}
}
在首次调用该类的get()
方法时,静态模块会进行输入,会抛出java.lang.NullPointerException: null
,第二次调用时会出现java.lang.NoClassDefFoundError: Could not initialize class com.example.demo.util.MapUtil
疑问
例二的例子在第一次调用时会报错,而我在项目中却没有报错误,也许是在哪里被拦截了吧;
最后
- 虽然问题不大,但是第一次遇到这样的问题,还是记录一下,增强记忆;
- 该问题涉及的知识点比较多,后面得花时间整理整理。
参考: