gpt4 book ai didi

java - UrlClassLoader 委托(delegate)和继承层次

转载 作者:搜寻专家 更新时间:2023-10-30 21:29:09 24 4
gpt4 key购买 nike

我对 UrlClassLoader 委托(delegate)层次结构和继承层次结构感到困惑。我创建了扩展 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 的目的是什么?

最佳答案

委托(delegate)优先模型

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

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

正在加载

那么当应用程序想要加载一个 HashMap 时会发生什么?当前的类加载器被要求加载 HashMap 类。在尝试任何事情之前,它会询问其父类,即扩展类加载器来加载该类。反过来,扩展类加载器委托(delegate)给引导类加载器,引导类加载器在 rt.jar 中找到类并加载它。

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

类加载器缓存

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

这里是检查缓存的地方

Class c = findLoadedClass(name);

URLClassLoaders

应用程序创建的 URLClassLoader 将应用程序 ClassLoader 作为父级。如果它遵循委托(delegate)优先模型,将在提供的 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?

这由 getClassLoader API 回答

[getClassLoader()] returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader.

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

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

引用资料

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

关于java - UrlClassLoader 委托(delegate)和继承层次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34160415/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com