2

我做了以下测试:

代码

public class FooMain {
   public static void main(String args[]) throws ClassNotFoundException {
      Class klass = Class.forName("com.sun.xml.internal.ws.spi.ProviderImpl");
   }
}

$CLASSPATH 环境变量

echo $CLASSPATH
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar:.
jar tvf /usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar | grep com.sun.xml.internal.ws.spi.ProviderImpl

 1742 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl$1.class
 1349 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl$2.class
12412 Wed Oct 24 18:52:52 EEST 2012 com/sun/xml/internal/ws/spi/ProviderImpl.class

所以寻找的类在 $CLASSPATH 上。

但是,在 Ant 的java任务和fork设置为"false"的情况下运行上述代码会失败,并且只有在fork设置为"true"时才会成功。

然而,这与ANT in Action 书中所写的内容背道而驰,该书在 pg 中注明。152 基本 Ant 的 java 任务使用 Ant 类路径运行,其中包括“CLASSPATH 环境变量中的所有内容”。

那么为什么当 fork 设置为“false”时,Ant 的 java 任务不能找到寻找的类,并且只有当fork设置为“true”时才能成功,即使在这两种情况下类都在 $CLASSPATH 上?

4

2 回答 2

4

任务使用一个特殊fork="false"<java>“隔离”类加载器,它只从任务自己的类路径(classpathref属性或<classpath>嵌套元素)加载类,除了一组特定的硬编码包前缀,如果它们将尝试从父加载器加载它们在任务自己的类路径中找不到。由于com.sun.xml不在此硬编码列表中,因此不会将其委托给父级,因此会给您一个ClassNotFoundException.

于 2013-01-20T23:07:01.380 回答
2

手册页对java任务的操作有如下解释:

在正在运行的 (Apache Ant) VM 中执行 Java 类,或者在指定时分叉另一个 VM。

如果在运行此任务时出现奇怪的问题,请设置 fork="true" 以使用新的 JVM。

使用 ANT 管理类路径

我强烈建议您始终 fork JVM 并利用 ANT 类路径管理工具:

<path id="runtime.path">
    <fileset dir="lib/runtimejars" includes="*.jar"/>
</path>

<java classname="???" fork="true" classpathref="runtime.path">
    <arg line="arg1 arg2 arg3"/>
</java>

为什么?如果您将构建移植到另一台机器上,您无法确定 CLASSPATH 变量的设置方式是否相同。

可执行jar

减少对 CLASSPATH 变量的依赖的另一种方法是创建一个可执行的 jar。以下答案演示了如何使用manifestclasspath任务创建一个可以嵌入到 jar 清单中的类路径:

于 2013-01-20T21:57:35.683 回答