【问题标题】:How a class is loaded by two class loader(assume both are URLClassLoader) at the same level in the java Class-loader loader Hierarchyjava Class-loader loader Hierarchy中同一级别的两个类加载器(假设都是URLClassLoader)如何加载一个类
【发布时间】:2019-05-10 04:13:16
【问题描述】:

最近我开始学习类加载器在 Java 中的工作原理。以下是我观察到的三点:

Point-1:每个类加载器都有一个父类加载器。当要求类加载器加载类或资源时,它会在尝试加载项目本身之前咨询其父类加载器。父级依次咨询其父级,依此类推。所以只有在所有祖先类加载器都找不到当前类加载器参与的项目之后。

Point-2:两个加载器加载的同一个类被视为两个不同的类实体。我们甚至不能将一个类(加载器 1)对象转换为另一个类(由 loader2 加载)。它会抛出 ClassCastException。

Point-3:子类加载器可以检查父类加载器的缓存,但是父类看不到加载的类 由孩子。

基于以上几点,我有两个问题:

情况: 我在同一个应用程序中创建了一个 URLClassloader 对象 url1 和另一个 URLClassloader 对象 url2。正如我们所知,默认情况下,两个类加载器都将具有相同的父类加载器。假设这里的父类加载器是 SystemClassLoader。

问题 1: url1 类加载器从位置 x/abc.jar 加载了一个类 A.class。再次 url2 想从同一个类加载同一个类 地点。 url2 会重新加载还是使用 url1 加载的相同?我试图检查,只有一次静态块被执行,所以相信的类只被加载一次。据我了解,这不满足第 1 点和第 3 点。

问题2: url2 类加载器是否可以检查url1 类加载器的缓存。与第 3 点有关。

【问题讨论】:

    标签: java classloader


    【解决方案1】:

    类加载器是完全独立的,所以你会得到两个不同的类。

    由于您没有发布 MCVE(最小、完整和可验证的示例),因此这里是使用任意选择的 .jar 文件的示例。

    public static void main(String[] args) throws Exception {
        String jarFile = "/path/to/commons-lang3-3.8.1.jar";
    
        URLClassLoader url1 = new URLClassLoader(new URL[] { new File(jarFile).toURI().toURL() });
        URLClassLoader url2 = new URLClassLoader(new URL[] { new File(jarFile).toURI().toURL() });
    
        Class<?> fractionClass1 = url1.loadClass("org.apache.commons.lang3.math.Fraction");
        Class<?> fractionClass2 = url2.loadClass("org.apache.commons.lang3.math.Fraction");
    
        Object oneHalf1 = fractionClass1.getField("ONE_HALF").get(null);
        Object oneHalf2 = fractionClass2.getField("ONE_HALF").get(null);
    
        System.out.println("url1 = " + url1);
        System.out.println("url2 = " + url2);
        System.out.println(" Same? " + (url1 == url2));
        System.out.println("fractionClass1 = " + fractionClass1);
        System.out.println("fractionClass2 = " + fractionClass2);
        System.out.println(" Same? " + (fractionClass1 == fractionClass2));
        System.out.println("oneHalf1 = " + oneHalf1);
        System.out.println("oneHalf2 = " + oneHalf2);
        System.out.println(" Same? " + (oneHalf1 == oneHalf2));
    }
    

    输出

    url1 = java.net.URLClassLoader@1e81f4dc
    url2 = java.net.URLClassLoader@4d591d15
     Same? false
    fractionClass1 = class org.apache.commons.lang3.math.Fraction
    fractionClass2 = class org.apache.commons.lang3.math.Fraction
     Same? false
    oneHalf1 = 1/2
    oneHalf2 = 1/2
     Same? false
    

    【讨论】:

      猜你喜欢
      • 2018-08-29
      • 2012-12-26
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多