使用URLClassLoader可以获得与默认ClassLoader相同的引用



我正在尝试测试一个类是否可以多次加载到jvm,但要使用不同的ClassLoader所以我的代码尝试两次加载一个类(类名"Tzvika")首先使用默认的ClassLoader并且在第二次尝试中使用URLClassLoader
问题是,我得到了URLClassLoader和默认ClassLoader的相同引用我做错了什么?

此处代码:

public static void main(String[] args) {
    Tzvika t1 = new Tzvika();
    System.out.println("t1 class loader: " + t1.getClass().getClassLoader());
    Tzvika t2 = null;
    try {
        URLClassLoader clsLoader = URLClassLoader.newInstance(new URL[] {new URL("file:/C://data/workspace/ashrait/tests/SampleClassLoader/bin/com/tzvika/sample/")});
        // same problem when i do this
        //URLClassLoader clsLoader = new URLClassLoader(new URL[] {new URL("file:/C://data/workspace/ashrait/tests/SampleClassLoader/bin/com/tzvika/sample/")});
        Class cls = clsLoader.loadClass("com.tzvika.sample.Tzvika");
        t2 = (Tzvika)cls.newInstance();
        System.out.println("t2 class loader: " + t2.getClass().getClassLoader());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这里是我的控制台输出:

t1 class loader: sun.misc.Launcher$AppClassLoader@1a52fdf
t2 class loader: sun.misc.Launcher$AppClassLoader@1a52fdf

创建没有父级的URLClassLoader

URLClassLoader clsLoader = URLClassLoader.newInstance(new URL[] {new URL("file:/C://data/workspace/ashrait/tests/SampleClassLoader/bin/com/tzvika/sample/")}, null);

还要注意,您应该指定类路径的根路径,即

URLClassLoader clsLoader = URLClassLoader.newInstance(new URL[] {new URL("file:/C://data/workspace/ashrait/tests/SampleClassLoader/bin")});

为了更好地阐明,URLClassLoader的构造函数状态为

URL将按照为类和指定的顺序进行搜索在指定的父类加载器中首次搜索后的资源

因此,当您尝试从这个ClassLoader加载一个类时,它将首先检查父ClassLoader,也就是引导类加载程序,是否存在该类。由于父类加载器已经加载了一个com.tzvika.sample.Tzvika类,它将返回它

现在,由于父类加载器和clsLoader加载的类是不同的,因此这些类的实例属于不同的类。因此,尽管两个ClassLoader都有com.tzvika.sample.Tzvika,但它们有很大的不同。

这就是不同ClassLoader的全部意义。

最新更新