2012-06-12 57 views

回答

2

的javadoc说以下有关class loaders

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

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

在某些情况下,您可能希望创建一个独立的类加载器,也就是不与应用程序类加载器链绑定的类加载器。在这些情况下,你可以创建一个父类为null的类加载器。 (即在URLClassLoader class中检查构造函数)

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

CNC中

我要说明我的答案。假设:

  • 我有一个名为Creature位于JAR文件的接口称为parent.jar
  • 我有一个名为Jedi的类,位于名为child.jar的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类是由类加载器加载,那么所有的类A依赖于 会的ClassLoader A.

是完全错误的加载。

+0

是的,其实我试图实现孤立的类加载器。我的疑惑是,在我提供的链接中,mainClass已经被URLClassLoader加载,那么它所依赖的所有类将被同一个加载器(或加载器的父加载器)加载,为什么我们需要调用''Thread.currentThread()setContextClassLoader(类加载器);''? –

+0

那么,如果你的类加载器是链中唯一的类加载器,那么你可以确定它将加载所有的类,但是如果你的链中有更多的类加载器(即绑定到不同的URL),那么一个父母最终可能会加载其孩子或大孩子或伟大的孩子要求的课程,对吧? –

+0

@ James.Xu我已经更新了我的答案,通过提供示例为您提供更详细的信息。 –

0

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

+0

感谢您的快速响应。在我提供的链接中,''mainClass''已经被URLClassLoader加载,那么它所依赖的所有类将被同一个加载器(或加载器的父加载器)加载,为什么我们需要调用''Thread。 currentThread()setContextClassLoader(类加载器);''? –

+0

该方法让你告诉代码你将要调用它应该使用某个类加载器。想象一下,你写一个运行webapps的服务器。该webapps将有很长的classpaths,但服务器会有短路径。服务器将由一个类加载器加载,但它必须使用具有较长类路径的类加载器加载该webapp代码。说实话,我仍然不明白为什么这是必要的。这个链接试图解释它http://impalablog.blogspot.com/2008/10/using-threads-context-class-loader-in.html。 –