最近用到了URLClassLoader的loadClass()方法,就写了个测试例子,结果出现了问题。具体问题如下所述:
[b]首先,给出测试代码,该代码贴到Main函数了直接可以运行[/b]:
[code="java"]URLClassLoader loader = null;
try {
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
//E:\mp_workspace\HttpServer2.0\webRoot 是工程下一目录,用来存放测试的class文件
String respository = new URL("file",null,” E:\mp_workspace\HttpServer2.0\webRoot”)toString();
urls[0] = new URL(null,respository,streamHandler);
loader = new URLClassLoader(urls);
} catch (Exception e) {
e.printStackTrace();
}
Class className = null;
try {
className = loader.loadClass(“Myclass”);
System.out.println(className.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Myclass myclass = null;
try {
myclass = (Myclass)className.newInstance();
myclass.test();
} catch (Exception e) {
e.printStackTrace();
}
[/code]
要测试的类Myclass.java的代码如下,注意它的[b]包名[/b]:
[code="java"]package com.test;
public class Myclass {
public void test() {
System.out.println("good byte");
}
public static void main(String[] args) {
System.out.println("hello word");
}
}[/code]
现在问题是运行上面测试代码是:当Myclass.java在包com.test里面时,运行上面的测试代码会报错。错误信息是:
[color=red]Exception in thread "main" java.lang.NoClassDefFoundError: Myclass (wrong name: com/test/Myclass)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)[/color]
[color=blue][size=medium]但是比较奇怪的是,我把Myclass类直接移到源文件src下载,即Myclass没有包名时,运行则通过,没有一点问题。[/size][/color]
我想,这与我还不太了解URLClassLoader这个类有关吧。请大家帮我看看,在你们的IDE上调试下,这个问题我琢磨了很久,还是想不出所以然啊。
还有,我的工程名是HttpServer2.0 ,我在工程下建了一个目录webRoot,专门用来放测试的class文件。上面的例子,就是我先通过eclipse编译了Myclass.java,在bin下生成了Myclass.class文件,然后我将该文件复制到webRoot目录下进行测试的。
最奇怪的一点是:[size=medium][color=blue]src下有Myclass.java类则上面测试没问题,否则会报错[/color][/size]
[quote] 还有,我的工程名是HttpServer2.0 ,我在工程下建了一个目录webRoot,专门用来放测试的class文件。上面的例子,就是我先通过eclipse编译了Myclass.java,在 bin下生成了Myclass.class文件,然后我将该文件复制到webRoot目录下进行测试的。[/quote]
[color=blue]如果Myclass是带包名的话, 如com.test, 则在bin/com/test目录下有Myclass.class文件, 将其复制到webRoot/com/test目录下, 而不是webroot目录
loader.loadClass("com.test.Myclass");
respository 中的那个路径就是webRoot的目录[/color]
你应该是看how tomcat works书籍吧,如果是把PrimitiveServlet放到java路径下(src-main-java)这里
String servletName = "PrimitiveServlet";
URLClassLoader urlClassLoader = null;
try {
URL[] urls = new URL[1];
urlClassLoader = new URLClassLoader(urls);
Class cls = urlClassLoader.loadClass(servletName);
Object object = cls.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
其实根本不需要载入指定webroot为servlet的路径,直接用上面空的URL就行了,为什么?
因为PrimitiveServlet已经被载入JVM里面了,在java目录下他就是没有包名,他的类名就是全限定名。但是这里为什么需要多此一举指定URL呢?
loader.loadClass(“Myclass”); 时必须使用全名,即需要包含你的包名。
而loader = new URLClassLoader(urls); 只是用于加载时的路径,相当于将你指定的目录加载到了CLASSPATH中。