类装入问题解密,第 3 部分: 处理更少见的类装入问题

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

这个四部分构成的文章系列研究 Java™ 的类装入问题,帮助应用程序开发人员理解和调试可能碰到的问题。在第 3 部分中,来自 IBM Hursley 实验室的作者 Lakshmi Shankar 和 Simon Burns 在本系列前两部分的基础之上,具体介绍了不同种类的类装入问题,包括与类路径、类可视性和垃圾收集有关的问题。

本文是本系列中四篇文章的第三篇,它研究了在 Java 开发过程中的一些更复杂、更少见的类装入问题。造成这些问题的原因通常无法直接从症状得出;所以,解决起来既困难又费时。与本系列以前的文章一样,我们仍然提供示例来演示问题,然后讨论各种解决技术。

在开始这篇文章之前,应当熟悉类装入委托模型,以及类链接的阶段和过程。我们强烈建议您从阅读本系列的 第一篇文章 开始。

与类路径有关的问题

有一个非常简单的问题通常与用户设置的类路径有关。清单 1 和清单 2 中的示例演示了这个问题。

测试用例创建了两个类装入器,每个类装入器使用的类路径看起来相同。但是,有一个微小但是却重大的区别:一个类路径末尾有 /,而另一个没有。在这两个类路径中的一个名为 cp 的子目录中有一个类 Z(在清单 2 中)。两个类装入器都试图装入 Z:

清单 1. ClasspathTest.java

import java.net.URL;

import java.net.URLClassLoader;

public class ClasspathTest {

String userDir;

URL withSlash;

URL withoutSlash;

ClasspathTest() {

try {

userDir = System.getProperty("user.dir");

withSlash = new URL("file://C:/CL_Article/ClasspathIssues/cp/");

withoutSlash = new URL("file://C:/CL_Article/ClasspathIssues/cp");

} catch (Exception e) {

e.printStackTrace();

}

}

void run() {

try {

System.out.println(withSlash);

URLClassLoader cl1 = new URLClassLoader(new URL[] { withSlash });

Class c1 = cl1.loadClass("Z");

System.out.println("Class Z loaded.");

System.out.println(withoutSlash);

URLClassLoader cl2 = new URLClassLoader(new URL[] { withoutSlash });

Class c2 = cl2.loadClass("Z");

System.out.println("Class Z loaded.");

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

new ClasspathTest().run();

}

}

清单 2. Z.java

public class Z {

}

这个测试用例产生以下输出:

file://C:/CL_Article/ClasspathIssues/cp/

Class Z loaded.

file://C:/CL_Article/ClasspathIssues/cp

java.lang.ClassNotFoundException: Z

at java.net.URLClassLoader.findClass(URLClassLoader.java:376)

at java.lang.ClassLoader.loadClass(ClassLoader.java:572)

at java.lang.ClassLoader.loadClass(ClassLoader.java:504)

at ClasspathTest.run(ClasspathTest.java:28)

at ClasspathTest.main(ClasspathTest.java:36)

可以看到,传递给每个 URLClassloader 的参数略有不同。提供给第一个类装入器 cl1 的类路径末尾有 /。提供给第二个类装入器 cl2 的类路径末尾没有 /。这个区别是显著的,因为类装入器假设不以 / 结尾的路径指向的是 JAR 文件。只有以 / 结尾的路径才被假定为指向目录。

因为 cl1 的类路径被当作目录,所以这个类装入器能够找到在这个位置的类 Z,并能够装入它。cl2 的类路径被假定为 JAR 文件;这个类装入器不能发现类 Z ,因为没有这个文件。所以,cl2.loadClass() 抛出 ClassNotFoundException。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航