编写了一个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异常
感谢解答:-)
[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中,就能成功运行了。
在我环境上运行没有任何问题。
你检查下你的java-home配置有没有问题?
[quote]谢谢您的解答。test.HelloWorld是打成helloworld.jar放在e盘下面的。问题应该是:运行Hello的main函数时classpath中没有这个jar包。我在几台机器上试都如此,问题不明。 [/quote]
Hello和ClassLoader是在什么位置?
test包下的两个类是否都打进jar包了,jar是从eclipse中导出的还是jar命令打的
从这里看,除了自定义的ClassLoader这个类名不对,其它都应该是没问题的。ClassLoader与java.lang里的重名了
改变一下 .classpath文件下面相关jar的路径。
确定jar包是放到E盘根目录了吧
检查下系统环境变量中的CLASSPATH的值,最好只保留 . 这个路径。
类名首字母大写 ,编译 javac +文件名.java 解释 java +文件名 路径要切换到你的java文件目录 cd .. 上一级 cd .. 上一级 , cd 目录 ,javac 文件名.java ,java 文件名
在代码里试试URLClassLoader的loadClass方法、findResource方法,如果是NoClassDefFound,这两个方法应该也找不到东西出来
改变一下 .classpath文件下面相关jar的路径。
因为你用myeclipse是它自动给你设置了正确的路径,你现在得自己手动设置。
你试试
Class<?> mainClass = Class.forName("test.Hello", true, loader);
用loader加载类test.Hello,因为helloworld.jar不存在该类,怕以委托给
systemclassloader,所以由systemclassloader加载了test.Hello类,
test.Hello再引用helloworld,系统当然用systemclassloader去加载他。
因为loader不是systemclassloader的父classloader(反过来成立),
所认找不到test.HelloWorld.
java -cp helloworld.jar test.ClassLoader
应该可以,因为systemclassloader就负责加载cp中的类。(具体原因,参考classloader委托原理,google找一找,再不行,contract me)
怕以-->所以
java -cp e;\helloworld.jar test.ClassLoader
test.ClassLoader 的路径也要加在cp中
不然去哪找
另外我第一次说的方法,在eclipse里应该没问题了吧
myeclipse直接运行是没有问题,但在命令行运行的时候,如下设置在本机就是正常的。
java -classpath E:\WorkspacesForJPBM\LoaderJAR\bin; test.ClassLoader,即使把bin目录设置成classpath.
:cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: