10

我在几个地方看到“Class.getClassLoader() 返回用于加载该特定类的 ClassLoader”,因此,我对以下示例的结果感到困惑:


package test;

import java.lang.*;

public class ClassLoaders { 
    public static void main(String[] args) throws java.lang.ClassNotFoundException{
      MyClassLoader mcl = new MyClassLoader();
      Class clazz = mcl.loadClass("test.FooBar");
      System.out.println(clazz.getClassLoader() == mcl); // prints false
      System.out.println(clazz.getClassLoader()); // prints e.g. sun.misc.Launcher$AppClassLoader@553f5d07
    }
}

class FooBar { }

class MyClassLoader extends ClassLoader { }

clazz.getClassLoader() == mcl 语句不应该返回 true 吗?有人可以解释我在这里缺少什么吗?

谢谢。

4

3 回答 3

17

每当您创建自己的类加载器时,它将附加在类加载器的树状层次结构中。为了加载一个类,类加载器首先将加载委托给它的父类。只有当所有的父母都没有找到类时,首先被要求加载类的加载器才会尝试加载它。

在您的特定情况下,加载被委托给父类加载器。尽管您要求 MyClassLoader 加载它,但加载的是父级。在这种情况下,它是 AppClassLoader。

于 2009-04-03T11:28:15.617 回答
6

引用ClassLoader 的 API 文档

ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例将在尝试查找类或资源本身之前将对该类或资源的搜索委托给其父类加载器。

于 2009-04-03T11:29:34.613 回答
-2

如果自定义类加载器将调用委托给虚拟机的类加载器,由谁加载类。clazz.getClassLoader() 将返回这个类加载器。

深入了解:ClassLoader 类的 Javadoc提供了以下对执行步骤顺序的解释:

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

  1. 调用 findLoadedClass(String) 来检查类是否已经加载。
  2. 在父类加载器上调用 loadClass 方法。如果 parent 为 null,则使用虚拟机内置的类加载器。
  3. 调用 findClass(String) 方法来查找类。

由于您在未更改方法的情况下继承了该方法,因此此行为将保持不变。步骤 2 将是加载类的步骤。当您调用 ClassLoader 的无参数构造函数时(自动地,因为您没有在 MyClassLoader 中定义构造函数),您会自动使用内置的 ClassLoader。

于 2009-04-03T11:27:35.273 回答