2

我在某处读过,如果class A被加载,ClassLoaderA那么所有A依赖的类都将被加载ClassLoaderA。这是真的吗?如果是真的,那为什么我们需要设置上下文类加载器呢?喜欢这个:http ://blog.markturansky.com/archives/21 ,在此先感谢。

4

2 回答 2

2

Javadocs 对类加载器说以下内容:

ClassLoader 类使用委托模型来搜索类和资源。ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例将在尝试查找类或资源本身之前将对该类或资源的搜索委托给其父类加载器。虚拟机的内置类加载器,称为“引导类加载器”,它本身没有父级,但可以作为 ClassLoader 实例的父级。

因此,您问题中的陈述显然是错误的。

在某些情况下,您可能希望创建一个隔离的类加载器,即不绑定到应用程序类加载器链的类加载器。在这些情况下,您可以创建一个父级为空的类加载器。(即检查URLClassLoader 类中的构造函数)

这意味着如果这个隔离的类加载器无法找到/加载给定的类,它将立即失败并显示ClassNotFoundException. 这也意味着您可以拥有两个独立的类加载器层次结构,而不会相互干扰。

-编辑-

我将说明我的答案。假使,假设:

  • 我有一个名为的接口,Creature位于名为parent.jar.
  • 我有一个名为的类Jedi位于名为child.jar.
  • 该类Jedi实现接口Creature

现在,让我们创建一个类加载器链,独立于当前系统链。

ClassLoader parent = new URLClassLoader(new URL[]{parentJar.toURL()}, null);
ClassLoader child = new URLClassLoader(new URL[]{childJar.toURL()}, parent);

现在,我们可以要求子类加载器加载该类Jedi

Class<?> klass1 = child.loadClass("com.star.wars.Jedi");

现在,如果您查询它的类加载器,您将看到它是由子类加载器加载的。到现在为止还挺好。但是它实现的接口呢。这取决于它,但是该Creature接口仅对其父类加载器可用,对吗?

好吧,如果您请求,klass1.getInterfaces()[0].getClassLoader()您会注意到它是父类加载器。

这证明了陈述:

如果类 A 由 ClassLoader A 加载,则 A 所依赖的所有类都将由 ClassLoader A 加载。

是完全错误的。

于 2012-06-12T03:09:16.227 回答
0

你读的是正确的。默认情况下,所有类只是相互引用并最终使用相同的 ClassLoader。您提供的链接解释了如何做相反的事情。在同一个 JVM 中加载的多个类可以具有相同的名称(包括包名称)但定义不同。通常,当它们来自同一库的不同版本时,就会发生这种情况。如何确保使用库版本 1 的代码始终看到版本 1,而使用库版本 2 的代码始终看到版本 2?如您提供的链接中所述,您可以通过引导类加载器隔离类加载器来执行此操作。

于 2012-06-12T03:09:24.180 回答