问题描述
我一直对UrlClassLoader委托层次结构和继承层次结构感到困惑.我创建了扩展UrlClassLoader的类并执行: childOfUrlClassLoader.getParent().getClass().getName()
这给了我: sun.misc.Launcher $ AppClassLoader
.之后,我访问了上述课程(源)
I have been confused with UrlClassLoader delegation hierarchy and inheritance hierarchy.I created class that extends UrlClassLoader and executed: childOfUrlClassLoader.getParent().getClass().getName()
which gave me:sun.misc.Launcher$AppClassLoader
.After this I pay a visit to mentioned above 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
.
Then I checked who is a parent of AppClassLoader. Expectedly I got sun.misc.Launcher$ExtClassLoader
and the parent of ExtClassLoader is null
.
我有几个问题:
1)谁加载了我的课程,因为 AppClassLoader.loadClass
的代码有一行
1) Who loads my class since the code of AppClassLoader.loadClass
has line
294 return (super.loadClass(name, resolve));
看起来像循环,不是吗?
It looks like loop, doesn't it?
2)为什么ExtClassLoader没有以 BootstrapClassLoader
作为父项,却没有 null
?
2) Why doesn't ExtClassLoader have BootstrapClassLoader
as a parent, but has null
?
3)出于什么目的,AppClassLoader类扩展了UrlClassLoader?
3) For which purpose AppClassLoader class extends UrlClassLoader?
推荐答案
委托优先模型
内置的Java ClassLoader遵循委托优先模型.这意味着ClassLoader将允许其父项在尝试自身加载之前先加载一个类.加载程序的层次结构的顶部是引导加载程序,其后是扩展类加载程序,即应用程序类加载程序.在应用程序类加载器下可以找到URLClassLoaders以及该应用程序创建的任何其他加载器.
The build-in java ClassLoaders follow a delegate-first model. This means that a ClassLoader will allow its parent to load a class before it tries to load it itself. The hierarchy of loaders has the bootstrap loader at the top, followed by the extension classloader, the application classloader. Under the application classloader can be found URLClassLoaders and any other loaders created by the application.
引导程序类加载器可以从rt.jar加载文件,该文件包含最基本的Java类,包括java.lang,java.io,java.util和java.net软件包中的类.扩展类加载器从Java安装中的其他jar文件加载类.是应用程序类加载器,它加载在类路径上找到的类,并且是应用程序启动时的当前类加载器.
The bootstrap classloader can load files from rt.jar which contains the most essential java classes including those in the java.lang, java.io, java.util and java.net packages. The extension classloader loads classes from other jar files in the java installation. It is the application classloader which loads the classes found on the classpath and which is the current classloader when an application starts.
正在加载
那么,当应用程序要加载HashMap时会发生什么?要求当前的类加载器加载HashMap类.在尝试任何操作之前,它要求其父级(即扩展类加载器)加载该类.反过来,扩展类加载器会委托给引导类加载器,该引导加载器会在rt.jar中找到该类并进行加载.
So what happens when an application wants to load a HashMap? The current classloader is asked to load the HashMap class. Before attempting anything, it asks its parent, the extension classloader to load the class. In turn the extension classloader delgates to the bootstrap classloader which finds the class in rt.jar and loads it.
如果要加载的类在类路径中,则该请求将像以前一样转到引导类加载器,以检查rt.jar.引导加载程序找不到该类,因此该任务被引回到扩展类加载程序,该扩展程序在Java安装程序中搜索该类.如果失败,该任务将返回到应用程序类加载器,后者会扫描该类的类路径.
If the class to be loaded is in the classpath, the request goes up to the bootstrap classloader as before to check rt.jar. The bootstrap loader fails to find the class, so the task is referred back to the extension classloader which searches the java installation for the class. When this fails the task reverts back to the application classloader which scans the classpath for the class.
ClassLoader缓存
在实践中,每个类加载器都有一个高速缓存,用于存储已加载的类,并在委派给父级之前先搜索该高速缓存,但这不会改变首先委派的原理.
In practice each classloader has a cache where classes already loaded are stored and the cache is searched before the delegation to the parent, but this does not alter the principle of delegating first.
这是检查缓存的地方
Class c = findLoadedClass(name);
URLClassLoaders
由应用程序创建的URLClassLoader将应用程序ClassLoader作为父项.如果它遵循委托优先模型,则将在提供的URL之前的类路径中找到类.
A URLClassLoader created by an application will have the application ClassLoader as a parent. If it follows the delegate-first model, classes will be found in the classpath before the supplied URL.
问题
1)谁加载了我的课程
1) Who loads my class
我在您的链接中看到了稍有不同的代码
I see slightly different code in your 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 }
如果父类未加载某个类,则会抛出ClassNotFoundException,该异常将被捕获并允许当前的ClassLoader查找该类
If a class is not loaded by the parent, it throws a ClassNotFoundException which is caught and allows the current ClassLoader to find the class
321 c = findClass(name);
2)为什么ExtClassLoader不能将BootstrapClassLoader作为父级,却具有null?
2) Why doesn't ExtClassLoader have BootstrapClassLoader as a parent, but has null?
getClassLoader API 对此进行了回答.
3)AppClassLoader类出于什么目的扩展了UrlClassLoader?
3) For which purpose AppClassLoader class extends UrlClassLoader?
考虑到应用程序类加载器不是特殊的,因为它加载了用户提供的类,而不是系统类.classpath实际上是URI的列表,因此URLClassLoader是合适的超类.
Consider that the application classloader is not special in that it loads classes supplied by the user, not system classes. The classpath is effectively a list of URIs so a URLClassLoader is a suitable superclass.
参考
关于类加载的文章很多,包括
There are many article on classloading including
这篇关于UrlClassLoader委派和继承层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!