JavaCompiler与自定义ClassLoader和FileManager



我希望编译源代码而不让计算机上存在依赖项。
示例:文件 A.java:

import some.pkg.B; 
public class A extends B {...}

我没有 B 源代码,我希望钩住 JavaFileManager 或自定义类加载器以获取有问题的符号(包"some.package"和类 B),然后使用我拥有的服务来检索源字符串。

编译代码:(输入文件有 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

编辑

在使用 API、浏览 JavaCompiler(旧版本)源代码并阅读编译概述之后,我仍然找不到可用于从语法树中为我提供符号的 API 钩子。似乎 API 需要按照 kschneid 的建议根据包名称获取所有资源。
我想到的一种解决方法是运行JavaCompiler并分析错误消息中缺少的符号。这样我就会知道需要哪些符号,获取它们并重新编译。
还有其他解决方法/解决方案吗?

(我假设你并没有真正使用"包"的包名称,因为那只是非法的......

自定义JavaFileManager应调用其list方法。希望这种表示法有意义,但该方法的参数组合应如下所示:

[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>实例有多困难,但我认为这就是所需的......

我发现在编译时钩入类的一个好方法是使用 Groovy AST 转换。你可以看看可以做什么

这里

虽然这不是普通的旧Java,但它可以是一个方便的工具。

最新更新