3

我有一个简单的自定义 ClassLoader

class CustomLoader extends ClassLoader {
    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        System.out.println("In the custom loader");
        throw new ClassNotFoundException();
    }
}

这是我正在尝试使用加载器的代码:

public static void main(String... str) throws ClassNotFoundException {
        CustomLoader loader = new CustomLoader();
        Class<?> cls = loader.loadClass("java.awt.Color");

        System.out.println(cls);
        System.out.println(cls.getClassLoader());
}

结果是可以预料的:

class java.awt.Color
null

在大多数文章中,您可以看到当您在自定义加载器上调用 loadClass 时,它首先会尝试在其缓存中查找类。如果找不到它,它会从父加载器(在本例中为应用程序加载器)调用 loadClass 方法。引导加载程序也是如此。之后,如果引导加载程序在其缓存中找不到该类,它会尝试在相应的源中找到它。如果加载器找不到它,子加载器会尝试查找,以此类推到自定义加载器。

如果您查看类加载器实现,您会发现它只是调用了 findClass 方法。但是考虑到我使用自定义加载器并且 java 具有多态性,无论父加载器调用 findClass,它们都会调用我的方法,对吗?

同时,据说java不会一次加载所有类,只有在需要时才加载。

如您所见,我们没有看到任何类转换异常,实际上我的重写方法甚至没有被调用。这意味着引导加载程序找到了 Color 类。

问题是我的错误在哪里?如果在 jvm 启动时 java 没有从 java... 包中加载所有类,它就不会在缓存中找到类 Color 并且它会调用我的覆盖方法。

(代码中的任何其他地方都没有使用 Color 类)

4

1 回答 1

2

根据 ClassLoader API,默认委托模型以这种方式工作

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

此委托模型在 ClassLoader.loadClass 方法中实现,要更改它,您应该重写 loadClass 方法而不是 findClass

于 2013-09-06T05:16:48.207 回答