UrlClassLoader 委托和继承层次结构

2024-06-26

我一直对 UrlClassLoader 委托层次结构和继承层次结构感到困惑。 我创建了扩展 UrlClassLoader 的类并执行:childOfUrlClassLoader.getParent().getClass().getName()这给了我:sun.misc.Launcher$AppClassLoader。 之后我访问了上述课程(source http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/sun/misc/Launcher.java#Launcher.AppClassLoader)

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$ExtClassLoaderExtClassLoader 的父级是null.


我有几个问题:

1)谁加载了我的类,因为代码AppClassLoader.loadClass有线

294    return (super.loadClass(name, resolve));

它看起来像循环,不是吗?

2)为什么没有 ExtClassLoaderBootstrapClassLoader作为父母,但有null?

3)AppClassLoader 类扩展 UrlClassLoader 的目的是什么?


代表优先模型

内置的 java 类加载器遵循委托优先模型。这意味着类加载器将允许其父级在尝试加载类之前先加载该类。加载器层次结构的顶部是引导加载器,其次是扩展类加载器和应用程序类加载器。在应用程序类加载器下可以找到 URLClassLoaders 和应用程序创建的任何其他加载器。

引导类加载器可以从 rt.jar 加载文件,其中包含最基本的 java 类,包括 java.lang、java.io、java.util 和 java.net 包中的类。扩展类加载器从 java 安装中的其他 jar 文件加载类。应用程序类加载器加载在类路径中找到的类,并且是应用程序启动时的当前类加载器。

正在加载

那么当应用程序想要加载 HashMap 时会发生什么?要求当前类加载器加载 HashMap 类。在尝试任何操作之前,它会要求其父级扩展类加载器加载该类。扩展类加载器又委托引导类加载器,引导类加载器在 rt.jar 中查找类并加载它。

如果要加载的类在类路径中,则请求将像以前一样转到引导类加载器以检查 rt.jar。引导加载程序无法找到该类,因此该任务将返回到扩展类加载器,该扩展类加载器在 java 安装中搜索该类。当此失败时,任务将恢复到应用程序类加载器,该类加载器扫描类的类路径。

类加载器缓存

实际上,每个类加载器都有一个缓存,其中存储已加载的类,并且在委托给父级之前搜索缓存,但这并不会改变首先委托的原则。

这是检查缓存的地方

Class c = findLoadedClass(name);

URL类加载器

由应用程序创建的 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作为父级,而是有null?

这是由获取类加载器 API http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getClassLoader()

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

3)AppClassLoader类扩展UrlClassLoader的目的是什么?

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

参考

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

  • Java 类加载的内部原理 http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html
  • 甲骨文教程 http://docs.oracle.com/javase/tutorial/ext/basics/load.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UrlClassLoader 委托和继承层次结构 的相关文章

随机推荐