我有一个简单的自定义 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 类)