繁体   English   中英

Java中的ClassLoader

[英]ClassLoader in Java

我正在使用Java中的类加载器,发现以下行为。 我可以从逻辑上对此进行推理,但是我不确定我所假设的是完全正确的。 我想知道这种行为的更正式解释。

我在想什么? 所以我有以下代码:

URL[] classURLs = {new URL("file://C:/Users/HP/IdeaProjects/test/out/production/test/")};
URLClassLoader urlClassLoader = new URLClassLoader(classURLs, null);
Class<?> personClass = urlClassLoader.loadClass("com.test.Person");

// the following line will give a ClassCastException
Person p = (Person) personClass.getDeclaredConstructor().newInstance();

现在,最后一行给出了ClassCastException

我的理由(猜测)为什么我得到一个ClassCastException :的类加载器personClassurlClassLoader ,而的类加载器Person类实际上是应用类加载器或系统类加载器( 请纠正我,如果我错了 )。 这些类加载器不匹配,我得到了ClassCastException (我在这里假设在类型转换时对类加载器执行检查)

因此,现在我继续通过以下方式探索和更改URLClassLoader的构造:

URLClassLoader urlClassLoader = new URLClassLoader(classURLs, Main.class.getClassLoader());

Main是封闭的类。 上面的代码使我免于ClassCastException

我对此的推理( 猜测 ):现在, urlClassLoader将应用程序类加载器作为其父级(此应用程序类加载器与用于加载Person类的加载器相同),在尝试urlClassLoader时,Java检查类加载器是否匹配,并且此检查继续与urlClassLoader的父级urlClassLoader ,向上一级进行类加载器匹配后,没有ClassCastException

我假设要与您要进行类型转换的类的类加载器进行检查,以检查要类型转换的对象的类的类加载器,如果不匹配,则尝试进行对象转换的类加载器的父级进行匹配并且这继续。

如果我在任何时候错了,请纠正我,并提供指向此行为的正式文档的指针。

我已经看到了此链接 ,但这未提供我所要求的详细信息。

您观察到的行为的正式文档在ClassLoader#loadClass()文档中:

用指定的二进制名称加载类。 此方法的默认实现按以下顺序搜索类:

  1. 调用findLoadedClass(String)以检查是否已加载该类。

  2. 在父类加载器上调用loadClass方法。 如果父级为null,则使用虚拟机内置的类加载器。

  3. 调用findClass(String)方法以查找类。

如果指定父类加载器,则URLClassLoader在尝试加载类本身之前检查父类加载器是否包含该类,这意味着它将从您的应用程序类路径中找到该类。

因此,如果您设置父类加载器,则此行:

Class<?> personClass = urlClassLoader.loadClass("com.test.Person");

表现与

Class<?> personClass = Main.class.getClassLoader().loadClass("com.test.Person");

如果com.test.Person类在应用程序类加载器上可用(必须为必需,否则无法加载您的Main类)。

您正在动态加载类,因此,由于您能够编译类“ Person”,这意味着您将两次加载同一类,从而导致类强制转换异常。

从类路径中删除该库,但是不会收到此错误,您也将失去对Person对象的访问。

当您加载它时,它仍然存在,但是访问它的方式是通过Reflection,并且您必须将“ Person”对象存储为“ Object”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM