日期:2014-05-20  浏览次数:21008 次

关于向URLClassLoader指定目录URL的问题
要写插件系统,避免不了要使用ClassLoader,一般都使用现有的URLClassLoader.之前用过URLClassLoader,忘记了不少用法
,所以今天再test test.
 
 
Java code
public class URLClassLoaderextends SecureClassLoader该类加载器用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。
这里假定任何以 '/' 结束的 URL 都是指向目录的。
如果不是以该字符结束,则认为该 URL 指向一个将根据需要打开的 JAR 文件。 



以上是中文版的URLClassLoader的doc,我从上面这段话里得到一个信息:可以向URLClassLoader指定目录的URL,并且URLClassLoader是会搜索目录下的文件的.

但事实却并非如此.

1.先看目录结构


2.代码
Java code
public class Main {

    /**
     * @param args
     * @throws MalformedURLException 
     * @throws ClassNotFoundException 
     */
    public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {

        File f = new File("lib");
        
        MyClassLoader loader = new MyClassLoader();
        File[] files = f.listFiles();
        for(File file: files){
            if(file.exists()){
                //loader.addFile(file); // A.添加lib下的所有文件到URLClassLoader
                System.out.println(file.getAbsolutePath());
            }
        }
        loader.addFile(f); // B.添加 lib目录到URLCLassLoader
        System.out.println(loader.getParent());
        
        String className = "org.apache.commons.lang.StringUtils";
        loader.loadClass(className);
        
    }
    
    static class MyClassLoader extends URLClassLoader{

        public MyClassLoader(URL[] urls) {
            super(urls);
        }
        
        public MyClassLoader(){
            super(new URL[]{});
        }
        
        public void addFile(File f) throws MalformedURLException{
            this.addURL(f.toURI().toURL());
            System.out.println("URL:" + f.toURI().toURL());
        }
        
    }

}

看第一个注释处
  若注释掉"loader.addFile(file)",则java.lang.ClassNotFoundException
  反之,程序正常运行

第二个注释处,有无"loader.addFile(f);"对结果并无影响

结论:向URLClassLoader添加目录是无效的,URLClassLoader并不会搜索或者将目录下的所有文件添加进classpath

另外,URLClassLoader的doc写得是不是有歧义?

欢迎斧正,拍砖.




------解决方案--------------------
LZ可能没完全理解文档说明
jar文件相当于一个文件夹
所以如果是加载文件夹,应该是相应的class文件在该文件夹内,而不是jar文件在该文件夹内
也就是说,加载文件夹,不会搜索该文件夹的jar,只会搜索该文件夹下的class文件
就好像classpath环境变量不能设置 xxxpath/*.jar一样,必须一个一个jar追加,所以只是设置xxxpath/,就只会搜索xxxpath下的class文件
------解决方案--------------------
这样一个目录结构是可以正常加载到org.apache.commons.beanutils.里面的类的


但是明显是不可能加载org.apache.commons.lang.StringUtils这个类,因为在lib目录中不存在
org\apache\commons\lang\StringUtils.class文件!

URLClassLoader不会试图从commons-lang-2.6.jar中加载的,因为你只向URLClassLoader中加入了lib目录,而不是commons-lang-2.6.jar