Gel*_*Luo 10 java compiler-construction classpath classloader in-memory
Eclipse的JDT编译器提供了一个接口INameEnvironment,该接口定义了findType(...)使您能够进行级联编译的方法.奇怪的是我想知道是否有任何方法可以使用标准的JDK编译工具包来做到这一点?
注意,该场景是一个模板引擎,它在内存编译中为模板文件生成的类进行相互依赖,并且它无法预测您遇到模板文件的顺序,因此Foo可能需要先编译才能进行父Bar编译,因此你需要一个机制来进行级联编译,这意味着在编译期间Foo你需要生成另一个源Bar并首先编译它以便继续Foo编译:一些代码如下:
private NameEnvironmentAnswer findType(final String name) {
try {
if (!name.contains(TemplateClass.CN_SUFFIX)) {
return findStandType(name);
}
char[] fileName = name.toCharArray();
TemplateClass templateClass = classCache.getByClassName(name);
// TemplateClass exists
if (templateClass != null) {
if (templateClass.javaByteCode != null) {
ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true);
return new NameEnvironmentAnswer(classFileReader, null);
}
// Cascade compilation
ICompilationUnit compilationUnit = new CompilationUnit(name);
return new NameEnvironmentAnswer(compilationUnit, null);
}
// So it's a standard class
return findStandType(name);
} catch (ClassFormatException e) {
// Something very very bad
throw new RuntimeException(e);
}
}
Run Code Online (Sandbox Code Playgroud)
根据我们的评论对话,我认为答案是明确的:不,你不能使用 JDK 编译器来做到这一点。当它请求包时,它确实为您提供了一个钩子,但不是特定的类依赖项。
据我所知,您能得到的最接近的是:
这是一篇带有代码的好文章,但需要对其进行调整以处理内存类。具体来说,您所描述的问题是由该JavaFileManager.list(...)方法处理的。您必须在此处返回已缓存在内存中的 JavaFileObjects。您很可能需要创建ForwardingJavaFileManager本文中描述的子类 - 尽管进行了修改以处理您正在使用的缓存类。
你可以用它来编译一些东西。如果返回错误,请使用正则表达式找出缺少的内容。生成/编译缺少的代码后,重试编译原始代码。
注意:它确实在某些时候要求依赖类的 FQN 作为 ForwardingFileManager.list(...) 中的 packageName 参数。那时我还没有尝试返回课程。它可能不起作用,因为包不匹配,但也许会。