答案 0 :(得分:5)
Java中的ClassLoader基于三个原则:委托,可见性和唯一性。如果父级无法查找或加载类,则委托原则将类加载的请求转发到父类加载器并仅加载该类。可见性原则允许子类加载器查看父类ClassLoader加载的所有类,但父类加载器无法查看子加载的类。唯一性原则允许只加载一次类,这基本上是通过委托实现的,并确保子类ClassLoader不会重新加载已经由父加载的类。
换句话说,如here所述:
Java中的类加载器是在树中组织的。按要求上课 loader确定过去是否已经加载了类, 查找自己的缓存。如果该类存在于缓存中 CL返回该类,否则,它将请求委托给父类。 如果未设置父级(是Null)或无法加载类和 抛出ClassNotFoundException,类加载器尝试加载 类本身并搜索自己的类文件路径。如果 可以加载它返回的类,否则返回ClassNotFoundException 被扔了。 缓存查找以递归方式从子进行到 parent,直到到达树根或在缓存中找到类。 如果到达了根,则类加载器尝试加载类和 展开从父到子的递归。总结一下我们有 以下顺序:
- 缓存
- 父
- 自
此机制可确保最靠近根目录的类加载器可以加载类。
答案 1 :(得分:2)
纯粹是效率问题。如果忘记了缓存,则类加载的顺序可确保Java系统类始终优先于应用程序类,并且类只能由链中的一个类加载器加载。因此,没有类在多个缓存中,因此搜索缓存的顺序没有任何功能差异。
换句话说,你可以搜索引导加载程序缓存,然后是扩展类加载器缓存,然后是系统类加载器缓存,然后开始尝试加载类,最终结果将完全相同。要做到这一点,需要一个额外的API来搜索加载的类,并且由于搜索缓存是一个非常快速的操作,因此带来的好处很少。
请注意,类可以由多个类加载器加载,但如果它们位于loader->父链中则不能加载。