首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > Ruby Rails >

怎么解决java.lang.NoClassDefFoundError-第二部分

2012-08-24 
如何解决java.lang.NoClassDefFoundError--第二部分如何解决NoClassDefFoundError--第二部分第一部分请看:

如何解决java.lang.NoClassDefFoundError--第二部分
如何解决NoClassDefFoundError--第二部分

第一部分请看: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.NoClassDefFoundErrorSimulatorjava.lang.NoClassDefFoundError SimulatorCurrent 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.NoCljava.lang.NoClassDefFoundError SimulatorCurrent 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.javCaused 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中验证,确保编译和运行期都能找到此类。

热点排行