1

我刚刚开始使用 Ant,但在让“运行”目标工作时遇到了问题。我的部分代码加载了一个属性文件,它总是找不到这个文件,除非我让我的运行目标使用新的 JVM。下面是一个非常简化的示例,“run”目标失败,“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);
        }
    }
}
4

1 回答 1

2

ANT 在读取包含您运行的指定类路径的 XML 文件时已经启动,实际上无法重置正在运行的 JVM 的类路径。相反,它会尝试附加到它,因为它与类加载器链一起使用;但是,您对类加载器的调用可能会获取根类加载器。你可能想做这样的事情:

this.getClass().getClassLoader().getResourceAsStream("com/example/test.properties");

这将强制类使用与加载相同的类加载器。这应该(希望)在正确的位置跳转到 ClassLoader 链,就好像它加载了当前类并且属性文件与当前类一起适当地“移动”了,那么属性文件应该可以通过同一个类加载器访问。

请注意,无论如何都有很多好的理由来分叉 JVM。在我看来,最重要的是摆脱整个 JVM 的 ANT 相关类。您不想意外地将运行时绑定到仅在软件构建过程中可用的类,并且如果要将类绑定到 ANT,则应将其作为第 3 方库进行管理(因此您可以控制版本它绑定到,绑定程度,在 ANT 的多个版本/发行版中以相同方式重现构建的能力等)

于 2011-05-09T16:12:56.800 回答