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