有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么findLoadedClass方法调用返回不同的结果

考虑自定义类加载器^ {< CD1> }

如果我按如下方式调用loadClass

ClassLoader loader = new ClassLoader(){}; 
loader.loadClass("java.util.ArrayList");
Method method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
method.setAccessible(true);
System.out.println(method.invoke(loader,"java.util.ArrayList"));

它输出null

但如果我替换

loader.loadClass("java.util.ArrayList"); 

Class.forName("java.util.ArrayList",true,loader);

它输出class java.util.ArrayList

有人能解释这个问题吗


共 (1) 个答案

  1. # 1 楼答案

    默认的ClassLoader实现按以下顺序执行类加载:

    1. Invoke findLoadedClass(String) to check if the class has already been loaded.
    2. Invoke the loadClass method on the parent class loader. If the parent is null the class loader built-in to the virtual machine is used, instead.
    3. Invoke the findClass(String) method to find the class.

    这是从Javadoc中直接提取的

    当您调用loadClass时,您的实现将委托给父类加载器,然后再尝试自己加载它。这恰好是您的系统类装入器

    在本例中,您的类已经在系统类加载器的类路径上,因此它被加载

    稍后调用findLoadedClass时,该方法仅检查指定的类加载器是否已加载该类。它不执行进一步的授权

    当您调用method.invoke(loader, "java.util.ArrayList")时,您正试图在CustomerClassLoader中找到加载的类。这会失败,因为执行加载的是父类加载器

    您可以通过调用系统类加载器上的方法来证明这一点,如下所示:

    method.invoke(ClassLoader.getSystemClassLoader(),"java.util.ArrayList")