我对UrlClassLoader委派层次结构和继承层次结构感到困惑。
我创建了扩展UrlClassLoader并执行的类:childOfUrlClassLoader.getParent().getClass().getName()
这给了我:
sun.misc.Launcher$AppClassLoader
。
在此之后,我访问了上面提到的课程(source)
249 static class AppClassLoader extends URLClassLoader {
//...
308 protected synchronized Class<?> loadClass(String name, boolean resolve)
309 throws ClassNotFoundException
310 {
311 // First, check if the class has already been loaded
312 Class c = findLoadedClass(name);
313 if (c == null) {
314 try {
315 if (parent != null) {
316 c = parent.loadClass(name, false);
317
// ...
329 return c;
330 }
然后我检查了谁是AppClassLoader的父级。我得到了sun.misc.Launcher$ExtClassLoader
,而ExtClassLoader的父级是null
。
我有几个问题:
1)由于AppClassLoader.loadClass
的代码有行
294 return (super.loadClass(name, resolve));
它看起来像循环,不是吗?
2)为什么ExtClassLoader没有BootstrapClassLoader
作为父级,但有null
?
3)为什么AppClassLoader类扩展了UrlClassLoader?
答案 0 :(得分:10)
代表优先模式
内置java ClassLoaders遵循委托优先模型。这意味着ClassLoader将允许其父级在尝试加载类之前加载它。加载器的层次结构在顶部有引导加载程序,后跟扩展类加载器,即应用程序类加载器。在应用程序类下,可以找到URLClassLoaders和应用程序创建的任何其他加载器。
bootstrap类加载器可以从rt.jar加载文件,其中包含最基本的java类,包括java.lang,java.io,java.util和java.net包中的java类。扩展类加载器从java安装中的其他jar文件加载类。它是应用程序类加载器,它加载在类路径中找到的类,以及应用程序启动时当前的类加载器。
正在加载
那么当应用程序想要加载HashMap时会发生什么?要求当前的类加载器加载HashMap类。在尝试任何事情之前,它会询问其父级,扩展类加载器加载该类。反过来,扩展类加载器继承到引导类加载器,它在rt.jar中找到类并加载它。
如果要加载的类在类路径中,请求将像以前一样上传到bootstrap类加载器以检查rt.jar。引导加载程序无法找到该类,因此该任务将返回到扩展类加载器,该类加载器在java安装中搜索该类。当此操作失败时,任务将恢复为应用程序类加载器,该类加载器将扫描类的类路径。
ClassLoader缓存
实际上,每个类加载器都有一个缓存,其中存储了已加载的类,并在委托给父代之前搜索缓存,但这并不会改变委托的原则。
这是检查缓存的地方
Class c = findLoadedClass(name);
<强> URLClassLoaders 强>
应用程序创建的URLClassLoader将应用程序ClassLoader作为父级。如果它遵循委托优先模型,则会在提供的URL之前的类路径中找到类。
问题
1)谁加载我的课程
我在链接中看到的代码略有不同
309 // First, check if the class has already been loaded
310 Class c = findLoadedClass(name);
311 if (c == null) {
312 try {
313 if (parent != null) {
314 c = parent.loadClass(name, false);
315 } else {
316 c = findBootstrapClass0(name);
317 }
318 } catch (ClassNotFoundException e) {
319 // If still not found, then invoke findClass in order
320 // to find the class.
321 c = findClass(name);
322 }
323 }
如果父类没有加载某个类,它会抛出一个被捕获的ClassNotFoundException,并允许当前的ClassLoader找到该类
321 c = findClass(name);
2)为什么ExtClassLoader没有BootstrapClassLoader作为父级,但是为空?
回答了这个问题[getClassLoader()]返回类的类加载器。某些实现可能使用null来表示引导类加载器。
3)为什么AppClassLoader类扩展了UrlClassLoader?
考虑到应用程序类加载器并不特殊,因为它加载了用户提供的类,而不是系统类。类路径实际上是一个URI列表,因此URLClassLoader是一个合适的超类。
<强>参考强>
关于类加载的文章很多,包括