从JDK6迁移到JDK7后,下一个代码失败并出现 ClassNotFoundException
CompilationTask task = cSysCompiler.getTask(null, cFileManager, cDiagnosticCollector, null, null, cUnitsToCompile);
boolean mSuccess = task.call();
Analyzer mAnalyzer = new Analyzer(); // Throws ClassNotFoundException
解决方法:
ClassLoader mSystemClassLoader = ClassLoader.getSystemClassLoader();
mSystemClassLoader.loadClass("ft.jopc.com.JavaBytecodeObject");
mSystemClassLoader.loadClass("ft.jopc.com.analyzer.Analyzer");
mSystemClassLoader.loadClass("ft.jopc.opccl.ClassLoaderListener");
…
ompilationTask task = cSysCompiler.getTask(null, cFileManager, cDiagnosticCollector, null, null, cUnitsToCompile);
boolean mSuccess = task.call();
Analyzer mAnalyzer = new Analyzer(); // No ClassNotFoundException
有谁知道为什么在找不到对task.call()类的调用之后?看起来系统类加载器在某种程度上被编译任务改变了?
答案 0 :(得分:3)
我们最近遇到了类似的问题,JavaFileManager的自定义实现重新定义(除其他外)
public ClassLoader getClassLoader(final Location location)
{
return getClass().getClassLoader();
}
不确定为什么会这样做,但在你的情况下,这在jdk6下工作正常。我们将jdk7问题精确定位到这个函数部分是因为它在单元测试期间失败了(类加载器是Launcher $ AppClassLoader),但在“生产模式”(类由自定义类加载器加载)中工作正常。更改此函数以使用StandardFileManager版本,甚至只将其封装在空的URLClassloader中,例如
return new URLClassLoader(new URL[]{}, getClass().getClassLoader());
解决了这个问题。
显然它与介绍URLClassloader以及因此AppClassLoader在jdk7中为“可关闭”有关,如下所示:
Thread [main] (Suspended (breakpoint at line 282 in URLClassLoader))
Launcher$AppClassLoader(URLClassLoader).close() line: 282 [local variables unavailable]
JavacProcessingEnvironment.close() line: 1257
JavaCompiler.initProcessAnnotations(Iterable<Processor>) line: 1004
JavaCompiler.compile(List<JavaFileObject>, List<String>, Iterable<Processor>) line: 821
Main.compile(String[], String[], Context, List<JavaFileObject>, Iterable<Processor>) line: 439
JavacTaskImpl.call() line: 132
然后,我必须承认我没有发现javadoc在这个主题上真的很清楚,但是看看jdk6 DefaultFileManager以及jdk7 BaseFileManager,似乎相当清楚,期望是提供一个临时文件管理器(因此需要关闭“如果可能”,而不是“通用”。
(我很乐意在任何情况下了解有关该主题的其他/最佳实践参考资料)