UrlClassLoader委托和继承层次结构

时间:2015-12-08 16:01:05

标签: java classloader

我对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?

1 个答案:

答案 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 API

回答了这个问题
  

[getClassLoader()]返回类的类加载器。某些实现可能使用null来表示引导类加载器。

3)为什么AppClassLoader类扩展了UrlClassLoader?

考虑到应用程序类加载器并不特殊,因为它加载了用户提供的类,而不是系统类。类路径实际上是一个URI列表,因此URLClassLoader是一个合适的超类。

<强>参考

关于类加载的文章很多,包括