我正在实现一个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()
检索。