我在某处读到过,如果class A由ClassLoaderA加载,那么A所依赖的所有类都将由ClassLoaderA加载。是真的吗?如果这是真的,那么为什么我们需要设置上下文类加载器?比如这个:http://blog.markturansky.com/archives/21,提前谢谢你。
发布于 2012-06-12 11:09:16
Javadoc对class loaders的描述如下
ClassLoader类使用委托模型来搜索类和资源。ClassLoader的每个实例都有一个关联的父类加载器。当被请求查找类或资源时,ClassLoader实例将把对类或资源的搜索委托给它的父类加载器,然后再尝试查找类或资源本身。虚拟机的内置类加载器,称为“引导类加载器”,本身没有父实例,但可以作为ClassLoader实例的父实例。
因此,你问题中的陈述显然是错误的。
在某些情况下,您可能希望创建一个独立的类加载器,即不绑定到应用程序类加载器链的类加载器。在这些情况下,您可以创建一个父类为null的类加载器。(例如,检查URLClassLoader class中的构造函数)
这意味着如果这个独立的类加载器不能找到/加载一个给定的类,它将立即失败,并返回一个ClassNotFoundException。这也意味着您可以拥有两个独立的类加载器层次结构,而不会相互干扰。
编辑--
我将举例说明我的答案。假设:
我在一个名为parent.jar.
Creature的接口,在一个名为child.jar.
Jedi的类,该类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-12 11:09:24
你读的是正确的。默认情况下,所有类只是相互引用,并以相同的ClassLoader结束。您提供的链接解释了如何执行相反的操作。加载到同一JVM中的多个类可以具有相同的名称(包括包名),但具有不同的定义。通常,当它们来自同一个库的不同版本时,就会发生这种情况。如何确保使用库版本1的代码总是看到版本1,而使用库版本2的代码总是看到版本2?您可以通过bootstrap ClassLoader使用ClassLoader隔离来完成此操作,如您提供的链接中所述。
https://stackoverflow.com/questions/10990013
复制相似问题