NoClassDefFoundError产生的原因有好几种,这里记录静态变量或静态块引起的。具体抛出的异常类似:
java.lang.NoClassDefFoundError: Could not initialize class xxx
JVM在加载类的时候,会初始化类里的静态变量,或执行静态块,如果这个时候抛出了异常,该类就会加载失败,那么以后任何使用到这个类的地方,都会抛出NoClassDefFoundError异常,如下面的例子:
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; }
执行结果如下:
第一次new java.lang.ExceptionInInitializerError at TestNoClassDefFoundError.getClassWithInitErrors(TestNoClassDefFoundError.java:12) at TestNoClassDefFoundError.main(TestNoClassDefFoundError.java:4) Caused by: java.lang.ArithmeticException: / by zero at ClassWithInitErrors.<clinit>(TestNoClassDefFoundError.java:42) ... 2 more ----------------------------------------------------- 第二次new java.lang.NoClassDefFoundError: Could not initialize class ClassWithInitErrors at TestNoClassDefFoundError.getClassWithInitErrors(TestNoClassDefFoundError.java:24) at TestNoClassDefFoundError.main(TestNoClassDefFoundError.java:4) ----------------------------------------------------- 第三次new java.lang.NoClassDefFoundError: Could not initialize class ClassWithInitErrors at TestNoClassDefFoundError.getClassWithInitErrors(TestNoClassDefFoundError.java:34) at TestNoClassDefFoundError.main(TestNoClassDefFoundError.java:4)
上述代码,第二次及以后使用到ClassWithInitErrors类的地方,都只会抛出NoClassDefFoundError错误,而且通常我们查看日志的时候,都会先看最新的日志,所以就不容易找到加载类失败的真正原因,对于这种情况,我们应该搜索java.lang.ExceptionInInitializerError错误,找到第一次加载类的时候的日志,才能看到失败的原因。
实例
错误日志:java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11Graphi
JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true" & JAVA_OPTS='-server -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true'