UrlClassLoader 委托和继承层次
UrlClassLoader delegation and inheritance hierarchy
我对 UrlClassLoader 委托层次结构和继承层次结构感到困惑。
我创建了扩展 UrlClassLoader 的 class 并执行了:childOfUrlClassLoader.getParent().getClass().getName()
这给了我:
sun.misc.Launcher$AppClassLoader
。
之后我访问了上面提到的 class (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) 谁加载我的 class 因为 AppClassLoader.loadClass
的代码有行
294 return (super.loadClass(name, resolve));
看起来像循环,不是吗?
2) 为什么 ExtClassLoader 没有 BootstrapClassLoader
作为父级,但有 null
?
3) AppClassLoader class 扩展 UrlClassLoader 的目的是什么?
委托优先模型
内置 java 类加载器遵循委托优先模型。这意味着 ClassLoader 将允许其父级在尝试加载 class 之前加载它。加载器的层次结构在顶部具有 bootstrap 加载器,然后是扩展 classloader,应用程序 classloader。在应用程序 classloader 下可以找到 URLClassLoaders 和应用程序创建的任何其他加载器。
bootstrap class加载器可以从 rt.jar 加载文件,其中包含最重要的 java classes,包括 java.lang、java.io、java.util 和 java.net 包。扩展 classloader 从 java 安装中的其他 jar 文件加载 classes。它是应用程序 classloader,它加载在 classpath 上找到的 classes,它是应用程序启动时的当前 classloader。
加载中
那么当应用程序想要加载 HashMap 时会发生什么?当前 classloader 被要求加载 HashMap class。在尝试任何事情之前,它会询问其父扩展 classloader 以加载 class。反过来,扩展 classloader 委托给 bootstrap classloader,后者在 rt.jar 中找到 class 并加载它。
如果要加载的 class 在 class 路径中,则请求像以前一样转到 bootstrap classloader 以检查 rt.jar. bootstrap 加载程序无法找到 class,因此该任务返回到扩展 class 加载程序,它在 java 安装中搜索 class。当这失败时,任务恢复到应用程序 classloader,它扫描 class 路径寻找 class.
ClassLoader缓存
实际上每个 classloader 都有一个缓存,其中存储了 classes 已经加载的并且在委托给父级之前搜索缓存,但这不会改变先委托的原则.
这是检查缓存的地方
Class c = findLoadedClass(name);
URL类加载器
由应用程序创建的 URLClassLoader 将应用程序 ClassLoader 作为父级。如果它遵循委托优先模型,classes 将在提供的 URL.
之前的 class 路径中找到
问题
1) 谁加载我的 class
我看到您的代码略有不同 link
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 }
如果一个 class 没有被父级加载,它会抛出一个 ClassNotFoundException 被捕获并允许当前的 ClassLoader 找到 class
321 c = findClass(name);
2) 为什么 ExtClassLoader 没有 BootstrapClassLoader 作为父级,而是有 null?
回答了这个问题
[getClassLoader()] returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader.
3) AppClassLoader class 扩展 UrlClassLoader 的目的是什么?
考虑到应用程序 classloader 并不特殊,因为它加载用户提供的 classes,而不是系统 classes。 classpath 实际上是一个 URI 列表,所以 URLClassLoader 是一个合适的 superclass.
参考资料
关于class加载的文章很多,包括
我对 UrlClassLoader 委托层次结构和继承层次结构感到困惑。
我创建了扩展 UrlClassLoader 的 class 并执行了:childOfUrlClassLoader.getParent().getClass().getName()
这给了我:
sun.misc.Launcher$AppClassLoader
。
之后我访问了上面提到的 class (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) 谁加载我的 class 因为 AppClassLoader.loadClass
的代码有行
294 return (super.loadClass(name, resolve));
看起来像循环,不是吗?
2) 为什么 ExtClassLoader 没有 BootstrapClassLoader
作为父级,但有 null
?
3) AppClassLoader class 扩展 UrlClassLoader 的目的是什么?
委托优先模型
内置 java 类加载器遵循委托优先模型。这意味着 ClassLoader 将允许其父级在尝试加载 class 之前加载它。加载器的层次结构在顶部具有 bootstrap 加载器,然后是扩展 classloader,应用程序 classloader。在应用程序 classloader 下可以找到 URLClassLoaders 和应用程序创建的任何其他加载器。
bootstrap class加载器可以从 rt.jar 加载文件,其中包含最重要的 java classes,包括 java.lang、java.io、java.util 和 java.net 包。扩展 classloader 从 java 安装中的其他 jar 文件加载 classes。它是应用程序 classloader,它加载在 classpath 上找到的 classes,它是应用程序启动时的当前 classloader。
加载中
那么当应用程序想要加载 HashMap 时会发生什么?当前 classloader 被要求加载 HashMap class。在尝试任何事情之前,它会询问其父扩展 classloader 以加载 class。反过来,扩展 classloader 委托给 bootstrap classloader,后者在 rt.jar 中找到 class 并加载它。
如果要加载的 class 在 class 路径中,则请求像以前一样转到 bootstrap classloader 以检查 rt.jar. bootstrap 加载程序无法找到 class,因此该任务返回到扩展 class 加载程序,它在 java 安装中搜索 class。当这失败时,任务恢复到应用程序 classloader,它扫描 class 路径寻找 class.
ClassLoader缓存
实际上每个 classloader 都有一个缓存,其中存储了 classes 已经加载的并且在委托给父级之前搜索缓存,但这不会改变先委托的原则.
这是检查缓存的地方
Class c = findLoadedClass(name);
URL类加载器
由应用程序创建的 URLClassLoader 将应用程序 ClassLoader 作为父级。如果它遵循委托优先模型,classes 将在提供的 URL.
之前的 class 路径中找到问题
1) 谁加载我的 class
我看到您的代码略有不同 link
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 }
如果一个 class 没有被父级加载,它会抛出一个 ClassNotFoundException 被捕获并允许当前的 ClassLoader 找到 class
321 c = findClass(name);
2) 为什么 ExtClassLoader 没有 BootstrapClassLoader 作为父级,而是有 null?
回答了这个问题[getClassLoader()] returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader.
3) AppClassLoader class 扩展 UrlClassLoader 的目的是什么?
考虑到应用程序 classloader 并不特殊,因为它加载用户提供的 classes,而不是系统 classes。 classpath 实际上是一个 URI 列表,所以 URLClassLoader 是一个合适的 superclass.
参考资料
关于class加载的文章很多,包括