我刚刚开始使用 Ant,在让"运行"目标工作时遇到了问题。我的部分代码加载了一个属性文件,除非我让我的运行目标使用新的 JVM,否则它总是找不到这个文件。下面是一个非常简单的示例,"运行"目标失败,"run_fork"目标有效。我的理解是 Ant 有自己的类加载器来替换默认的类加载器,所以我想这在某种程度上与搜索路径有关。有什么方法可以更改我的代码以使这项工作而无需分叉新的 JVM?
构建.xml:
<project name="PropsExample" default="compile" basedir=".">
<property name="src" location="src"/>
<property name="bin" location="bin"/>
<target name="init">
<tstamp/>
<mkdir dir="${bin}"/>
</target>
<target name="compile" depends="init">
<javac includeAntRuntime="false" srcdir="${src}" destdir="${bin}"/>
<copy todir="${bin}">
<fileset dir="${src}" includes="**/*.properties"/>
</copy>
</target>
<target name="clean">
<delete dir="${bin}"/>
<delete dir="${dist}"/>
</target>
<target name="run" depends="compile">
<java classname="com.example.Test">
<classpath>
<pathelement location="${bin}"/>
</classpath>
</java>
</target>
<target name="run_fork" depends="compile">
<java fork="true" classname="com.example.Test">
<classpath>
<pathelement location="${bin}"/>
</classpath>
</java>
</target>
示例代码:
package com.example;
import java.util.Properties;
import java.io.InputStream;
public class PropertiesLoader {
public static String getProperty() throws Exception {
InputStream in = ClassLoader.getSystemResourceAsStream("com/example/test.properties");
if ( in == null ) {
throw new Exception("Cannot find test.properties");
}
Properties p = new Properties();
p.load(in);
in.close();
return p.getProperty("test");
}
}
和:
package com.example;
public class Test {
public static void main(String[] args) throws Exception {
try {
System.out.println(PropertiesLoader.getProperty());
} catch ( Exception e ) {
e.printStackTrace(System.out);
}
}
}
读取包含运行指定类路径的 XML 文件时已经启动,实际上无法重置正在运行的 JVM 的类路径。 相反,它试图在类加载器链中使用时附加到它;但是,您对类装入器的调用可能会抓取根类装入器。 您可能想要执行以下操作:
this.getClass().getClassLoader().getResourceAsStream("com/example/test.properties");
这将强制类使用与其加载相同的类加载器。 这应该(希望)在正确的位置跳转到 ClassLoader 链中,就好像它加载了当前类并且属性文件与当前类一起适当地"移动",那么属性文件应该可以通过相同的类加载器访问。
请注意,无论如何,有很多很好的理由来分叉JVM。 在我看来,最重要的是摆脱整个 JVM 中的 ANT 相关类。 您不希望意外地将运行时绑定到仅在软件构建过程中可用的类,并且如果您想将类绑定到 ANT,则应将其作为第三方库进行管理(因此您可以控制它绑定到的版本、绑定程度、跨多个版本/发行版 ANT 以相同方式重现构建的能力, 等)