我希望在没有机器上存在依赖关系的情况下编译源代码
示例:文件A.java:
import some.pkg.B;
public class A extends B {...}
我没有B源存在,我想挂钩JavaFileManager或自定义ClassLoader以获取有问题的符号(包'some.package'和B类)然后使用我有的服务检索源字符串。
编译代码:(inputFiles有A.java)
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
CustomClassLoader classLoader = new CustomClassLoader();
StandardJavaFileManager standardfileManager = compiler.getStandardFileManager(this, null, null);
JavaFileManager fileManager = new CustomFileManager(standardfileManager, output, classLoader);
CompilationTask task = compiler.getTask(null, fileManager, this, null, null, inputFiles);
boolean result = task.call();
编译时没有触发JavaFileManager(getFileForInput ..)和我的类加载器(findClass,loadClass ..)上的钩子,我收到错误消息:
A.java:#: package some.pkg does not exist
A.java:#: cannot find symbol
symbol: class B
EDIT
在使用API之后,浏览JavaCompiler(旧版本)源代码并阅读Compilation Overview我仍然无法找到一个API钩子,我可以使用它来为语法树提供符号。似乎API需要根据kschneid建议的包名获取所有资源。
我想到的一个解决方法是运行JavaCompiler并分析缺失符号的错误消息。这样我就会知道需要哪些符号,得到它们并重新编译
还有其他解决方法/解决方案吗?
答案 0 :(得分:4)
(我假设你并没有真正使用“package”的包名,因为这只是非法的......)
您的自定义JavaFileManager
应该调用其list
方法。希望这种符号有意义,但args与该方法的组合应如下所示:
[PLATFORM_CLASS_PATH, some, [CLASS], false]
[CLASS_PATH, some, [SOURCE, CLASS], false]
[PLATFORM_CLASS_PATH, some.pkg, [CLASS], false]
[CLASS_PATH, some.pkg, [SOURCE, CLASS], false]
我不确定您的特定环境创建适当的Iterable<JavaFileObject>
实例会有多困难,但我认为这就是所需要的......
答案 1 :(得分:1)
我发现在编译时挂钩类的好方法是使用Groovy AST Transformation。您可以查看可以执行的操作here
虽然这不是简单的旧java,但它可以是一个方便的工具来了解