根据我的阅读,当JVM需要一个类时,将发生以下事件:
请求被发送到应用程序类加载器以加载类。
应用程序类加载器将请求委托给扩展类加载器。
扩展类加载器将请求委托给Bootstrap类加载器。
Bootstrap类加载器尝试从Boottrap类路径加载类。如果在那里找到类,则将其加载。
如果引导类路径中不存在类,则扩展类加载器尝试从扩展类路径加载该类。
如果甚至在扩展类路径中也不存在类,则应用程序类加载器尝试从应用程序类路径(即CLASSPATH环境变量路径)加载类。
如果甚至那里都不存在类,则抛出ClassNotFoundException。
题:
当每个类加载请求最终都必须交给Bootstrap类加载器时,那么JVM为什么要承担首先请求应用程序类加载器的开销,然后让它逐渐将请求委托给Bootstrap类加载器。
为什么不直接请求Bootstrap类加载器?
是否有任何特定原因,或者我缺少某些东西,需要阅读更多有关的信息?
JVM并不专门寻找应用程序级的类加载器。相反,当触发类C的类加载时(通过加载引用尚未加载的类的类D或通过类D内部的反射)而未指定类加载器,则加载请求为定向到D的定义加载程序,通常是应用程序加载程序。然后,默认策略是委派给扩展程序和引导加载程序,但是从技术上讲,这种行为不是必需的。
这样做的一个主要原因是,如果您有某种共享类型,则需要在使用它的所有协作类的某些祖先类加载器中对其进行定义,因为类型是在运行时通过其全名和它们的组合来标识的。装载机。 (OSGi使用此规则将类的可见性限制为专门声明对它们的依赖性的捆绑软件。)
请注意,如果类D(例如,java.net.URL)由引导加载程序定义,则它加载的任何类C(例如,java.lang.String)都将由引导加载程序立即加载。
JVM规范的有关加载和链接的部分提供了有关解析和加载过程的最终详细信息。
如您所说,"然后,默认策略是委派给扩展程序和引导加载程序,但是此行为在技术上不是必需的"。 这正是我的问题。 保持这种行为背后的思考过程是什么?
@GauravKumar我正在更新,我想我现在就回答。 基本上,您希望类型由最高共同祖先类加载器定义,以便可以由所有子加载器共享。
您能否提供一个示例来解释您要在此处说的话。 谢谢
类加载器有3个原则:
代表
能见度
独特性
check this article: http://javarevisited.blogspot.co.id/2012/12/how-classloader-works-in-java.html
根据可见性原则,Application或System类加载器可以看到所有已加载的类文件,而Bootstrap或Primordial无法看到。
as Application class loader is child of Bootstrap class loader
为了确保一个类仅被加载一次(确保唯一性),应首先将加载类的请求发送到Application / System类加载器。
希望这会有所帮助。