Java类加载器加载器层次结构

时间:2019-05-10 04:13:16

标签: java classloader

最近我已经开始学习classloader在Java中的工作原理。以下是我观察到的三点:

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

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

要点3::子类加载器可以检查父类加载器的缓存,但父类看不到已加载的类    由孩子。

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

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

问题1::url1类加载器已从位置x / abc.jar加载了类A.class。再次url2要从相同的类加载相同的类    位置。 url2将重新加载还是将使用url1加载的相同URL?我试图检查一次,只有执行了静态块,所以被信任的类仅被加载一次。根据我的理解,这不能满足Point-1和Point-3的要求。

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

1 个答案:

答案 0 :(得分:0)

类加载器是完全独立的,因此您将获得两个不同的类。

由于您没有发布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