JavaCompiler具有自定义ClassLoader和FileManager

Che*_*rel 10 java classloader java-compiler-api

我希望在没有机器上存在依赖关系的情况下编译源代码.
示例:文件A.java:

import some.pkg.B; 
public class A extends B {...}
Run Code Online (Sandbox Code Playgroud)

我没有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();
Run Code Online (Sandbox Code Playgroud)

JavaFileManager(getFileForInput ..)和我的类加载器(findClass,loadClass ..)上的钩子在编译时没有触发,我收到错误消息:

A.java:#: package some.pkg does not exist
A.java:#: cannot find symbol
symbol: class B
Run Code Online (Sandbox Code Playgroud)

编辑

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

ksc*_*eid 4

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

您的自定义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]
Run Code Online (Sandbox Code Playgroud)

我不确定您的特定环境创建适当的Iterable<JavaFileObject>实例有多困难,但我认为这就是所需要的......