介绍
首先来说明一下NoClassDefFoundError和ClassNotFoundException的区别。
NoClassDefFoundError表明一个类在编译时是能找到的,但是在运行时找不到了。
ClassNotFoundException表示在运行时尝试加载类时找不到这个类。它不会在编译时去查找。
可能的原因
-
类不在类路径上(Classpath)
比如缺少了某些JAR包,或者Jar包没有被放在类路径上,或者JAR包改名字了因此找不到。
-
你可能通过jar命令运行的程序,并且类不在
manifest
文件中ClassPath
属性定义的路径上这个可以通过
("")
来打印类路径查看是否有你的类所在的路径。 -
有启动脚本覆盖了Classpath环境变量
通过-classpath选项来指定类路径,如果指定类路径成功运行了,那么就是Classpath被覆盖了。
-
因为
NoClassDefFoundError
是的子类,因此也可能是因为如本地库依赖找不到
-
检查日志文件中是否有
ExceptionInitializerError
错误,因为如果类静态初始化失败也可能会导致抛出NoClassDefFoundError
因为JVM初始化一个类时是线程安全的,所以如果你利用类的静态代码块来实现线程安全,但是在静态代码块中抛出了异常,那么这个类可能会抛出NoClassDefFoundError。同时如果你查看日志文件的话,应该也有
ExceptionInitializerError
,因为正式由于ExceptionInitializerError
触发了:Could not initialize class
。如下面的代码会因为静态代码块失败抛出NoClassDefFoundError:
/** * Java program to demonstrate how failure of static initialization subsequently cause * in Java. * @author Javin Paul */ public class NoClassDefFoundErrorDueToStaticInitFailure { public static void main(String args[]){ List<User> users = new ArrayList<User>(2); for(int i=0; i<2; i++){ try{ (new User((i))); //will throw NoClassDefFoundError }catch(Throwable t){ (); } } } } class User{ private static String USER_ID = getUserId(); public User(String id){ this.USER_ID = id; } private static String getUserId() { throw new RuntimeException("UserId Not found"); } } Output at (:23) Caused by: : UserId Not found at (:41) at .<clinit>(:35) ... 1 more : Could not initialize class at (:23)
-
如果是在J2EE环境中,则也可能是由于类在多个类加载器中的可见性问题。
比如说有一个类
User
同时出现类WAR文件和EJB-JAR文件中,假设有一个子类加载器ChildClassLoader同时加载WAR包中和EJB-JAR包中的User
类,那么这时候当EJB-JAR中的代码引用类User
时,EJB-JAR包的类加载器ClassLoader找不到类User
,因为它是被子类加载器ChildClassLoader加载了。这个例子举的有点模糊,因为什么情况下会是EJB-JAR包的类
User
由子类加载器加载,而EJB-JAR包中的其他类由类加载器自身而不是子类加载器加载呢? -
如果你是用的是ANT来进行构建jar包,那么要确保在ANT脚本中能拿到正确的classpath值并且追加到
文件。
-
也可能是因为权限问题从而导致无法读取JAR包。
-
XML配置书写错误导致根本没有这个类。
-
编译过的类应该在它自己的包下却不在那个包下。
-
编译后的类文件缺失。比如编译后删除某个类,那么在运行时会直接抛出NoClassDefFoundError,而不会再有ExceptionInitializerError,参考第5条。
参考:/2011/06/#axzz6oZiNtVnD