- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我对 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/
我正在尝试将多个水平链接的 Button 和 TextView 垂直链接为 View 集,但仍保持平面 View 层次结构。这是我的初始布局和代码:
到目前为止,我已经在Google BigQuery上训练了几种模型,目前我需要查看模型的外观(即架构,损失函数等)。 有没有办法获取这些信息? 最佳答案 仔细阅读文档后,我可以说该功能尚不存在。我什至
本文实例讲述了PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)。分享给大家供大家参考,具体如下: 前言: 深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个
我是一名优秀的程序员,十分优秀!