为什么A.class.getClassLoader()不返回loader.loadClass使用的加载器(" A")

时间:2017-09-20 10:54:38

标签: java reflection classloader

在此测试用例中,我们通过特定的类加载器实例加载类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();
  }
}

而且,这是运行类App

的输出
Main: ClassLoaderGw@6d06d69c
A.<cinit>: sun.misc.Launcher$AppClassLoader@73d16e93

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

2 个答案:

答案 0 :(得分:2)

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

在这种情况下,您的A类位于父类加载器的类路径中,因此 将加载它。

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

  

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

基本上,您不能......除非GwClassloader负责加载课程A

你可以使运作吗?好吧......如果你使用了不同的类加载策略,你可以。也许。如果GwClassloader能够找到A的字节码并且自己调用defineClass,那么它将成为A的类加载器。

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

答案 1 :(得分:1)

the Javadoc

中对此进行了描述
  

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

     
      
  • 调用findLoadedClass(String)以检查该类是否已加载。
  •   
  • 在父类加载器上调用loadClass方法。如果父级为null,则使用内置于虚拟机的类装入器。
  •   
  • 调用findClass(String)方法以查找类。
  •   

您的ClassLoadersun.misc.Launcher$AppClassLoader1作为父级,因为正如default constructor的Javadoc所述(在ClassLoaderGw类中隐式调用,因为有import socket import sys from _thread import * host = '127.0.0.1' port = 6666 s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: s.bind((host,port)) except socket.error as e: print(str(e)) s.listen(5) print ('waiting for clinet') def threaded_client(conn): k=1 conn.send(str.encode('Welcome You are connected')) while True: k=k+1 conn.send(str.encode('Loop',k)) while True: conn, addr = s.accept() print ('connected to : ' + addr[0] + str(addr[1])) start_new_thread(threaded_client,(conn,)) 类没有明确的构造函数):

  

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