URLClassLoader加载class文件的疑惑

最近用到了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中。