如何解决NoClassDefFoundError--第二部分
第一部分请看: http://vipcowrie.iteye.com/blog/1561291
本文面向的是JAVA初学者,建议你们自己编译和运行例子程序。
本文包含了NoClassDefFoundError的原因分析和例子程序,并且给出了建议的处理策略。
NoClassDefFoundError 问题原因1:缺少jar包
首先最常见的原因是classpath的配置问题。例子程序:
本例子程序尝试创建一个新的CallerClassA实例,然后执行他的一个方法,此方法引用了类ReferencingClassA,本例子演示了classpath问题导致的NoClassDefFoundError ,本例子还打印了当前的classloader chain的情况,以便进一步的分析。这个打印信息对你以后分析此类问题也很有帮助的:
程序
打印classloader工具类:
正常运行 :
异常重现 :
发生了什么?当你在classpath中不包含guava的引用的时候,由于ReferencingClassA在运行期引用了此类,导致了classloader报告找不到此类,从而出现NoClassDefFoundError。
classloader分析
注意:
sun.misc.Launcher$AppClassLoader是系统的classloader,负责根据classpath设置在启动的时候加载应用需要的class。
sun.misc.Launcher$ExtClassLoader是扩展classloader,负责从java_home/lib/etc以及其他使用java.ext.dirs配置的目录从加载扩展java class。
从打印结果可以看出,sun.misc.Launcher$ExtClassLoader是系统classloader的实际父类。
建议处理策略
分析异常堆栈,找到缺少的java类名称,在classpath中验证,确保编译和运行期都能找到此类。
第一部分请看: http://vipcowrie.iteye.com/blog/1561291
本文面向的是JAVA初学者,建议你们自己编译和运行例子程序。
本文包含了NoClassDefFoundError的原因分析和例子程序,并且给出了建议的处理策略。
NoClassDefFoundError 问题原因1:缺少jar包
首先最常见的原因是classpath的配置问题。例子程序:
本例子程序尝试创建一个新的CallerClassA实例,然后执行他的一个方法,此方法引用了类ReferencingClassA,本例子演示了classpath问题导致的NoClassDefFoundError ,本例子还打印了当前的classloader chain的情况,以便进一步的分析。这个打印信息对你以后分析此类问题也很有帮助的:
程序
- public class NoClassDefFoundErrorSimulator {
- public static void main(String[] args) {
- System.out
- .println("java.lang.NoClassDefFoundError Simulator");
- // Print current Classloader context
- System.out.println("\nCurrent ClassLoader chain: "
- + ClassloaderUtil.getCurrentClassloaderDetail());
- // 1. Create a new instance of CallerClassA
- CallerClassA caller = new CallerClassA();
- // 2. Execute method of the caller
- caller.doSomething();
- System.out.println("done!");
- }
- }
- public class CallerClassA {
- private final static String CLAZZ = CallerClassA.class.getName();
- static {
- System.out.println("Classloading of " + CLAZZ + " in progress..."
- + ClassloaderUtil.getCurrentClassloaderDetail());
- }
- public CallerClassA() {
- System.out.println("Creating a new instance of "
- + CallerClassA.class.getName() + "...");
- }
- public void doSomething() {
- // Create a new instance of ReferencingClassA
- ReferencingClassA referencingClass = new ReferencingClassA();
- }
- }
- public class ReferencingClassA {
- private final static String CLAZZ = ReferencingClassA.class.getName();
- static {
- System.out.println("Classloading of " + CLAZZ + " in progress..."
- + ClassloaderUtil.getCurrentClassloaderDetail());
- }
- public ReferencingClassA() {
- System.out.println("Creating a new instance of "
- + ReferencingClassA.class.getName() + "...");
- Maps.newHashMap();
- }
- public void doSomething() {
- // nothing to do...
- }
- }
打印classloader工具类:
- public class ClassloaderUtil {
- public static String getCurrentClassloaderDetail() {
- StringBuffer classLoaderDetail = new StringBuffer();
- Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();
- ClassLoader currentClassLoader = Thread.currentThread()
- .getContextClassLoader();
- classLoaderDetail
- .append("\n-----------------------------------------------------------------\n");
- // Build a Stack of the current ClassLoader chain
- while (currentClassLoader != null) {
- classLoaderStack.push(currentClassLoader);
- currentClassLoader = currentClassLoader.getParent();
- }
- // Print ClassLoader parent chain
- while (classLoaderStack.size() > 0) {
- ClassLoader classLoader = classLoaderStack.pop();
- // Print current
- classLoaderDetail.append(classLoader);
- if (classLoaderStack.size() > 0) {
- classLoaderDetail.append("\n--- delegation ---\n");
- } else {
- classLoaderDetail.append(" **Current ClassLoader**");
- }
- }
- classLoaderDetail
- .append("\n-----------------------------------------------------------------\n");
- return classLoaderDetail.toString();
- }
- }
正常运行 :
- java -classpath .;../guava-12.0.jar NoClassDefFoundError.NoClassDefFoundErrorSimulator
- java.lang.NoClassDefFoundError Simulator
- Current ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Classloading of NoClassDefFoundError.CallerClassA in progress...
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Creating a new instance of NoClassDefFoundError.CallerClassA...
- Classloading of NoClassDefFoundError.ReferencingClassA in progress...
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Creating a new instance of NoClassDefFoundError.ReferencingClassA...
- done!
异常重现 :
- java -classpath . NoClassDefFoundError.NoCl
- java.lang.NoClassDefFoundError Simulator
- Current ClassLoader chain:
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Classloading of NoClassDefFoundError.CallerClassA in progress...
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Creating a new instance of NoClassDefFoundError.CallerClassA...
- Classloading of NoClassDefFoundError.ReferencingClassA in progress...
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -----------------------------------------------------------------
- Creating a new instance of NoClassDefFoundError.ReferencingClassA...
- Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/collect/Maps
- at NoClassDefFoundError.ReferencingClassA.<init>(ReferencingClassA.java:28)
- at NoClassDefFoundError.CallerClassA.doSomething(CallerClassA.java:31)
- at NoClassDefFoundError.NoClassDefFoundErrorSimulator.main(NoClassDefFoundErrorSimulator.jav
- Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps
- at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
- at java.security.AccessController.doPrivileged(Native Method)
- at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
- at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
- at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
- ... 3 more
发生了什么?当你在classpath中不包含guava的引用的时候,由于ReferencingClassA在运行期引用了此类,导致了classloader报告找不到此类,从而出现NoClassDefFoundError。
classloader分析
注意:
- Classloading of NoClassDefFoundError.CallerClassA in progress...
- -----------------------------------------------------------------
- sun.misc.Launcher$ExtClassLoader@addbf1
- --- delegation ---
- sun.misc.Launcher$AppClassLoader@19821f **Current ClassLoader**
- -------------------------
sun.misc.Launcher$AppClassLoader是系统的classloader,负责根据classpath设置在启动的时候加载应用需要的class。
sun.misc.Launcher$ExtClassLoader是扩展classloader,负责从java_home/lib/etc以及其他使用java.ext.dirs配置的目录从加载扩展java class。
从打印结果可以看出,sun.misc.Launcher$ExtClassLoader是系统classloader的实际父类。
建议处理策略
分析异常堆栈,找到缺少的java类名称,在classpath中验证,确保编译和运行期都能找到此类。