11

我希望在机器上不存在依赖项的情况下编译源代码。
示例:文件 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

编辑

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

4

2 回答 2

4

(我假设您并没有真正使用“包”的包名,因为那是非法的......)

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

于 2012-05-29T20:16:31.683 回答
1

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

虽然这不是普通的旧 java,但它可以是一个方便的工具来了解

于 2012-06-04T07:58:17.330 回答