0

我正在实现一个 ant 任务作为另一个类的包装器,该类使用系统类加载器加载其他几个类。现在,任务在这些其他类的同一个 jar 中,所以我想知道为什么它没有找到它们,因为任务正在运行

请注意,我的类在$CLASSPATHenv 变量中。如果我不会出现问题export LOCALCLASSPATH=$CLASSPATH

最小的例子:

<taskdef name="mytask" classname="my.package.MyTask"  />

<target name="compile">
    <mytask />
</target>

你可以很容易地看到这里的问题

public class MyTask extends Task {
   public void execute() throws BuildException {
    try {
        ClassLoader cl = ClassLoader.getSystemClassLoader();

        // this will only print the ant jar file path
        for(URL url: ((URLClassLoader)cl).getURLs()){
        log(url.getFile());
        }

        cl.loadClass("my.package.OtherClass"); // throws an exception

    } catch (Exception ex) {
        throw new BuildException(ex);
    }
  }

}
4

1 回答 1

0

shell 脚本在ant内部修改了类路径,因此 SystemClassLoader 只包含“真实”类路径的最小部分

tl;博士:使用

    ClassLoader cl = Thread.currentThread().getContextClassLoader();

代替

    ClassLoader cl = ClassLoader.getSystemClassLoader();

来自邮件列表,Rainer Noack

如果您通过 shell 脚本启动 ant,它使用的是 oata.launcher.Launcher.java

这个类稍微重新组织了类路径。环境变量 CLASSPATH 和类路径命令行参数被剥离并替换为用于启动 ant 的最小类路径。系统类加载器的子类加载器是使用原始 CLASSPATH 条目创建的。然后使用这个类加载器加载 oata.Project。

问题在于实际上没有改变加载器,ClassLoader.getSystemClassLoader()可以使用Thread.currentThread().getContextClassLoader().

于 2013-03-27T09:16:16.587 回答