takemu 2011-08-27 00:19
浏览 324
已采纳

使用setContextClassLoader抛出NoClassDefFoundError异常的问题

编写了一个ClassLoader类,把E:\\helloworld.jar(这个jar中包含test.HelloWorld类)加入到classpath中,然后invoke() “test.Hello类”中的main函数,这个main函数依赖helloworld.jar中的方法

//ClassLoader.java
public class ClassLoader {
    public static void main(String[] args) throws Throwable{    
        
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Hello!");
            }
        });
        ArrayList<URL> classPath = new ArrayList<URL>();
        classPath.add(new File("E:\\helloworld.jar" + "/").toURL());

        URLClassLoader loader = new URLClassLoader(classPath.toArray(new URL[0]));
        Thread.currentThread().setContextClassLoader(loader);
        Class<?> mainClass = Class.forName("test.Hello", true, loader);
        
        Method main = mainClass.getMethod("main", new Class[] { Array
                .newInstance(String.class, 0).getClass() });
        String[] newArgs = Arrays.asList(args).subList(0, args.length)
                .toArray(new String[0]);
        try {
            main.invoke(null, new Object[] { newArgs });
        } catch (InvocationTargetException e) {
            throw e.getTargetException();
        }
    }
}
//Hello.java
package test;
public class Hello {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        test.HelloWorld.print();
    }
}
//HelloWorld.class/helloworld.jar
package test;
public class HelloWorld {
    public static void print() {
        // TODO Auto-generated method stub
        System.out.println("Hello World!");
    }
}


在eclipse中可以运行,因为我将helloworld.jar引入工程。在命令行下运行时就报NoClassDefFoundError异常



 

感谢解答:-)

 

  • 写回答

16条回答 默认 最新

  • weixin_42565855 2011-08-29 01:35
    关注

    [quote]

    Hello和ClassLoader是在什么位置?

    e:\java\workspace\jobutil\bin\test.Hello
    e:\java\workspace\jobutil\bin\test.ClassLoader

    [quote]
    URLClassLoader loader = new URLClassLoader(classPath.toArray(new URL[0]));

    14. Thread.currentThread().setContextClassLoader(loader);

    15. Class<?> mainClass = Class.forName("test.Hello", true, loader);

    [/quote]

    Class.forName的时候,loader会将加载动作先自下向上委托给其父类加载,而
    加载的时候默认路径包含了当前路径,所以loader的父类AppClassLoader能在
    当前路径下也就是bin下面找到Hello,所以AppClassLoader加载Hello成功,
    而当Hello调用HelloWorld的时候,也就会使用AppClassLoader去加载HelloWorld,在路径中加载失败,所以报异常,你把bin目录下的Hello删掉,
    打包放在E:\helloworld.jar中,就能成功运行了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(15条)

报告相同问题?

悬赏问题

  • ¥15 解决一个加好友限制问题 或者有好的方案
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥30 求解达问题(有红包)