Ant System Class Loader不尊重$ CLASSPATH,尊重$ LOCALCLASSPATH

时间:2013-03-13 10:45:39

标签: ant classpath classloader

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

请注意我的课程在$CLASSPATH env变量中。如果我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);
    }
  }

}

1 个答案:

答案 0 :(得分:0)

ant shell脚本在内部重新编写类路径,因此SystemClassLoader只包含“真实”类路径的最小部分

tl; dr:使用

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

而不是

    ClassLoader cl = ClassLoader.getSystemClassLoader();

从邮件列表Rainer Noack

  

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

     

这个类重新组织了类路径。 env变量CLASSPATH   并删除classpath命令行参数并替换为   用于启动ant的最小类路径。一个儿童类加载器   系统类加载器是使用原始CLASSPATH条目创建的。   然后使用此类加载器加载oata.Project。

问题是ClassLoader.getSystemClassLoader()中的加载器实际上是不受影响的,可以使用Thread.currentThread().getContextClassLoader()检索更改的加载器(即,尊重$ CLASSPATH,-lib等的加载器)。 / p>