类加载器:委托层次结构算法

时间:2018-08-06 17:50:58

标签: java

我们知道,类加载器子系统使用“委托层次结构算法”来加载类。我很好奇理解其实现背后的行为或逻辑。即,即使该类存在于当前目录中(应用程序/系统类加载器可能知道它),“ Boot Strap Loader”仍具有优先级,并委派给其子级。无法更改或改进吗?

2 个答案:

答案 0 :(得分:1)

理论上,您可以更改此行为,但是可能会出现非常非常奇怪的问题。

假设您有多层类加载器:

例如您的类加载器->一些父类加载器(例如webapp容器类加载器)-> system + bootsrap类加载器。

所以现在您的代码尝试从guava加载ImmutableMap,并且guava.jar对于“您的类加载器”和“ webapp容器类加载器”都是可见的。

您决定不委派,而是自己加载。这就是您获得ImmutableMap实例的方式。另一方面,“ webapp容器类加载器”也从他自己的guava.jar文件中加载了自己的ImmutableMap-因为那时他无法访问“您的类加载器”,唯一的方法是自己加载丢失的东西。 >

因此,现在您有两个ImmutableMap类,它们被认为是不同的(因为是由不同的类加载器加载的),如果从不同版本的guava.jar加载它们,则它们可能实际上是不同的。到目前为止,这还是“可以的”。 当您尝试将那个ImmutableMap类的实例跨边界传递到Webapp代码时,会发生地狱。这就是ClassCastException发生的地方,并带有一条奇怪的消息“ ImmutableMap类无法转换为ImmutableMap”。

为避免这种情况,请始终先调用父类加载器。

如果您100%确定该类的对象实例永远不会传递到使用其他类加载器加载的类中-那么您很安全-但是您永远不会100%保证。

一些与框架相关的类加载器不委托(例如Jboss,也许还有一些SpringBoot魔术类),但是他们完全知道自己在做什么。

答案 1 :(得分:0)

我想以下可能是此逻辑/实现的原因

  1. 由于对象是Java中所有驻留在“ java.lang”程序包中的类的父级,并且此程序包驻留在“ rt.jar”中,因此可能会优先考虑“ Bootstrap Class Loader”

  2. 大多数自定义 类需要使用内置Java语言功能,例如使用String或int,它们的定义在“ rt.jar”中再次可用,并且将由“ Bootstrap Class Loader”加载,因此可能会赋予其优先级。