java - 为什么这个类可以被Java类加载器加载两次?

标签 java classloader

这段代码可以通过两个不同的类加载器加载同一个类两次。

import java.net.URL;
import java.net.URLClassLoader;

public class Main {
    public static void main(String[] args) throws Exception {
        URL childAndParentClassesLocation = new URL("file:///C:\\Users\\Machi\\Desktop\\tobeloaded-1.0-SNAPSHOT.jar");
        ClassLoader cl1 = new URLClassLoader(new URL[]{childAndParentClassesLocation}, Main.class.getClassLoader());
        ClassLoader cl2 = new URLClassLoader(new URL[]{childAndParentClassesLocation}, Main.class.getClassLoader());
        Class child1 = cl1.loadClass("example.ToBeLoaded");
        Class child2 = cl2.loadClass("example.ToBeLoaded");
        System.out.println(child2 == child1);
        System.out.println(child2.equals(child1));

    }
}

但是 URLClassLoader 将应用程序类加载器作为父级。根据双亲委托(delegate)原则,ToBeLoaded类不应该被Application ClassLoader加载一次且仅一次吗?

最佳答案

如果父委托(delegate)原则有效,那么您是对的。但这并不总是理想的行为。

在 JEE 容器中,这因设计而异。想象一下两个不同的应用程序引用同一个类(名为 mypackage.MyClass)。但由于某种原因,一个应用程序需要版本 1 中的库“mypackage”,而另一个应用程序需要版本 2 中的库“mypackage”。而且两者是不兼容的。

因此,JEE 容器为每个应用程序分配一个类加载器,每个应用程序都将加载该类的特定版本。它们并行驻留在内存中,并且它们是截然不同的不同类型,因此如果您尝试将一种类型转换为另一种类型,您将看到引发异常。

因此,要真正了解两个类是否相同,不仅要比较它们的完全限定类名,还要比较它们所属的类加载器。我不知道在运行时 JVM 会检查两个类是否相同(内容方面),因为它可能会在您的示例中弹出。

关于java - 为什么这个类可以被Java类加载器加载两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75206840/

相关文章:

java - 创建表的实体

java - 类 XXX 的无参数构造函数不存在

Java 类加载器无法在 java.lang.Class 的类上调用 newInstance()

java - 读取 JAR 文件内的文件

java - mvn Sonar :sonar running Error: cannot be cast to org. sonar.java.resolve.JavaSymbol$TypeJavaSymbol

Java7 Bootstrap : Checking class without loading?

java - 以编程方式添加组件的样式与 XML 布局中的样式不同

java - 删除一些 HTML 标签但保留 Span 标签的正则表达式

java.lang.NoSuchMethodError : org. jboss.logging.Logger.getMessageLogger(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Object - Tomcat 8

java - 检查富文本编辑器中的空文本