我对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?
代表优先模型
内置的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作为父级,但是为空?
这可以通过getClassLoader API来解决
[getClassLoader()]返回类的类加载器.某些实现可能使用null来表示引导类加载器.
3)为什么AppClassLoader类扩展了UrlClassLoader?
考虑到应用程序类加载器并不特殊,因为它加载了用户提供的类,而不是系统类.类路径实际上是一个URI列表,因此URLClassLoader是一个合适的超类.
参考
关于类加载的文章很多,包括
Java ClassLoading的内部结构
Oracle教程