Java 为什么A.class.getClassLoader()不返回loader.loadClass(“A”)使用的加载程序

Java 为什么A.class.getClassLoader()不返回loader.loadClass(“A”)使用的加载程序,java,reflection,classloader,Java,Reflection,Classloader,在这个测试用例中,我们通过一个特定的类加载器实例加载一个类a,即GwClassLoader。但是,A.class.getClassLoader()没有检索到该类加载器?这是测试用例: class A{ static { ClassLoader loader = A.class.getClassLoader(); System.out.println("A.<cinit>: " + loader); } } class ClassLoaderGw extend

在这个测试用例中,我们通过一个特定的类加载器实例加载一个类
a
,即
GwClassLoader
。但是,
A.class.getClassLoader()
没有检索到该类加载器?这是测试用例:

class A{
  static {
    ClassLoader loader = A.class.getClassLoader();
    System.out.println("A.<cinit>: " + loader);
  }
}

class ClassLoaderGw extends ClassLoader { }

public class App {
  public static void main(String [] args)  throws ClassNotFoundException,  InstantiationException,  IllegalAccessException {
    ClassLoaderGw loader = new ClassLoaderGw();
    System.out.println("Main: " + loader);
    Class<?> klass = loader.loadClass("A");
    Object obj = klass.newInstance();
  }
}
如何在类
A
的静态构造函数中获取
GwClassLoader
的实例?

中描述了这一点:

加载具有指定二进制名称的类。此方法的默认实现按以下顺序搜索类:

  • 调用findLoadedClass(字符串)检查该类是否已加载
  • 调用父类加载器上的loadClass方法。如果父级为null,则使用虚拟机内置的类加载器
  • 调用findClass(String)方法来查找该类
您的
ClassLoader
sun.misc.Launcher$AppClassLoader1
作为父级,因为如的Javadoc中所述(在
ClassLoaderGw
类中隐式调用,因为没有显式构造函数):

使用getSystemClassLoader()方法返回的类加载器作为父类加载器,创建一个新的类加载器


ClassLoaderGw
只是扩展
ClassLoader
,而不重写任何方法。因此,它将遵循标准
loadClass
方法()的策略。。。首先委托给父类加载器

在本例中,您的
类位于父类加载器的类路径上,因此将加载它

最后一个难题是
getClassLoader()
返回实际加载类的类加载器,而不是您要求加载的类加载器


如何在类A的静态构造函数中获取GwClassLoader的实例

基本上,你不能。。。除非
GwClassloader
负责加载类
A

你能让它工作吗?好。。。如果您使用不同的类加载策略,您可以。大概如果
GwClassloader
能够找到
A
的字节码并调用
defineClass
本身,那么它将是
A
的类加载器


但是,您需要担心父类加载器也可能加载类
A
。如果发生这种情况,您可能同时存在两种不同的
A
类型。这可能会在意外的地方导致类强制转换异常。

已解决。通过调用
defineClass
,它将成为预期类的
classloader
。这里是针对的新实现
Main: ClassLoaderGw@6d06d69c
A.<cinit>: sun.misc.Launcher$AppClassLoader@73d16e93