我被UrlClassLoader委托层次结构和继承层次结构混淆了。我创建了扩展UrlClassLoader的类,并执行了:childOfUrlClassLoader.getParent().getClass().getName(),它给了我:sun.misc.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$ExtClassLoader,而ExtClassLoader的父母是null。
我有几个问题:
1),他加载了我的类,因为AppClassLoader.loadClass的代码有行
294 return (super.loadClass(name, resolve));它看起来像循环,不是吗?
2)为什么ExtClassLoader没有把BootstrapClassLoader作为父母,而是有null
3) AppClassLoader类是为了什么目的扩展UrlClassLoader的?
发布于 2015-12-11 17:17:04
代表-first model
内置的java ClassLoaders遵循委托优先模型。这意味着ClassLoader将允许它的父类在尝试加载类之前加载它。加载器的层次结构在顶部有引导加载器,后面是扩展类加载器,即应用类加载器。在应用程序下,可以找到URLClassLoaders和应用程序创建的任何其他加载器。
引导类加载器可以从rt.jar加载文件,其中包含最基本的java类,包括java.lang、java.io、java.util和java.net包中的类。扩展类加载器从java安装中的其他jar文件加载类。应用程序类加载器加载在类路径上找到的类,在应用程序启动时它是当前的类加载器。
在动作中的加载
那么,当应用程序想要加载HashMap时会发生什么呢?当前的类加载器被要求加载HashMap类。在尝试任何操作之前,它会要求它的父类扩展类加载器加载该类。然后,扩展类加载器将删除到引导类加载器,引导类加载器在rt.jar中找到类并加载它。
如果要加载的类在类路径中,则请求会像以前一样到达引导类加载器以检查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作为父级,而具有null?
这是由getClassLoader API回答的
getClassLoader()返回该类的类加载器。有些实现可能使用null来表示引导类加载器。
3) AppClassLoader类扩展UrlClassLoader的目的是什么?
请考虑应用程序类加载器不是特殊的,因为它加载由用户提供的类,而不是系统类。类路径实际上是URI的列表,因此URLClassLoader是一个合适的超类。
参考资料
有许多关于类加载的文章,包括
https://stackoverflow.com/questions/34160415
复制相似问题