Ant系统类装入器不支持$CLASSPATH,而是支持$LOCALCLASSPATH



我正在实现一个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);
    }
  }
}

ant shell脚本在内部重新制作类路径,因此SystemClassLoader只包含"真实"类路径的最小部分

使用

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

代替

    ClassLoader cl = ClassLoader.getSystemClassLoader();

来自邮件列表,Rainer Noack:

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

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

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

相关内容

  • 没有找到相关文章