Java 为什么findLoadedClass方法调用返回不同的结果?;
考虑一个自定义类加载器Java 为什么findLoadedClass方法调用返回不同的结果?;,java,classloader,Java,Classloader,考虑一个自定义类加载器类CustomClassLoader扩展类加载器 如果我调用loadClass,如下所示 ClassLoader loader = new ClassLoader(){}; loader.loadClass("java.util.ArrayList"); Method method = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class); method.setAccessible(tru
类CustomClassLoader扩展类加载器
如果我调用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");
与
它输出类java.util.ArrayList
有人能解释这个问题吗?默认的
ClassLoader
实现按以下顺序执行类加载:
loadClass
时,您的实现将在尝试加载父类加载器之前委托给父类加载器。这恰好是您的系统类装入器
在本例中,您的类已经在系统类加载器的类路径上,因此它被加载
稍后调用findLoadedClass
时,该方法仅检查指定的类加载器是否已加载该类。它不执行进一步的授权
调用method.invoke(loader,“java.util.ArrayList”)
时,您试图在CustomerClassLoader
中找到加载的类。这会失败,因为执行加载的是父类加载器
您可以通过调用系统类加载器上的方法来证明这一点,如下所示:
method.invoke(ClassLoader.getSystemClassLoader(),"java.util.ArrayList")
默认的
ClassLoader
实现按以下顺序执行类加载:
loadClass
时,您的实现将在尝试加载父类加载器之前委托给父类加载器。这恰好是您的系统类装入器
在本例中,您的类已经在系统类加载器的类路径上,因此它被加载
稍后调用findLoadedClass
时,该方法仅检查指定的类加载器是否已加载该类。它不执行进一步的授权
调用method.invoke(loader,“java.util.ArrayList”)
时,您试图在CustomerClassLoader
中找到加载的类。这会失败,因为执行加载的是父类加载器
您可以通过调用系统类加载器上的方法来证明这一点,如下所示:
method.invoke(ClassLoader.getSystemClassLoader(),"java.util.ArrayList")
什么是
CustomClassLoader
?由于我们不知道该类是什么以及它是做什么的,所以不可能知道它的findLoadedClass
方法是做什么的。我相信findLoadedClass
只检查ClassLoader
是否加载了该类,它不会委托给其父类。由于ArrayList
是一个核心类,它不是由您的自定义ClassLoader
@Jesper CustomClassLoader加载的,它只是扩展了ClassLoader并继承了ClassLoader的方法。findLoadedClass方法是由ClassLoader提供的,所以您只需编写ClassLoader=new ClassLoader(){}
?@matt我能想到的唯一一件事是findLoadedClass
的文档说(我的重点):“如果Java虚拟机已将此加载程序记录为具有该二进制名称的类的初始加载程序,则返回具有给定二进制名称的类。否则返回null”。启动加载器的定义似乎是。我猜Class#forName(String,boolean,ClassLoader)
使指定的ClassLoader
成为“启动加载器”。什么是CustomClassLoader
?由于我们不知道该类是什么以及它是做什么的,所以不可能知道它的findLoadedClass
方法是做什么的。我相信findLoadedClass
只检查ClassLoader
是否加载了该类,它不会委托给其父类。由于ArrayList
是一个核心类,它不是由您的自定义ClassLoader
@Jesper CustomClassLoader加载的,它只是扩展了ClassLoader并继承了ClassLoader的方法。findLoadedClass方法是由ClassLoader提供的,所以您只需编写ClassLoader=new ClassLoader(){}
?@matt我能想到的唯一一件事是findLoadedClass
的文档说(我的重点):“如果Java虚拟机已将此加载程序记录为具有该二进制名称的类的初始加载程序,则返回具有给定二进制名称的类。否则返回null”。启动加载器的定义似乎是。我猜Class#forName(String,boolean,ClassLoader)
会使指定的ClassLoader
成为“启动加载器”。但是如果我将“loader.loadeclass”(“java.util.ArrayList”);”替换为“Class.forName”(“java.util.ArrayList”),则它会输出“Class java.util.ArrayList”“你怎么解释这件事呢?”安萱我不知道你在问什么。我想我已经解释过了。如果可能,对loader.loadClass
的调用将加载到loader
的父类加载器上。对Class.forName
的调用将仅在给定的类加载器上加载。这是因为两个不同的调用导致了两种不同的类加载机制。另外,您有什么参考说明该类将仅在给定的类加载器上加载?当您调用类时