具有自定义 ClassLoader 和 FileManager 的 JavaCompiler

标签 java classloader java-compiler-api

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

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

我没有 B 源,我希望 Hook 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 ..) 上的 Hook 在编译时没有触发,我收到错误消息:

A.java:#: package some.pkg does not exist
A.java:#: cannot find symbol
symbol: class B

编辑

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

最佳答案

(我假设您并没有真正使用包名称“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]

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

关于具有自定义 ClassLoader 和 FileManager 的 JavaCompiler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10767048/

相关文章:

java - getSystemResourceAsStream() 返回 null

java - 是否有 TreeVisitor 用于按评估顺序访问表达式树?

java - 编译在另一个 java 代码中的字符串中可用的 java 代码

java - 注释处理器

java - 引用数组列表中的值对,然后比较它们

Java JNA 使用 Keyhook 回调

Java 类加载器无法在 java.lang.Class 的类上调用 newInstance()

android - 如何防止丢失的、未使用的注释类使我的程序崩溃?

java - Java中为什么要用.class来获取Class对象呢?为什么不像 Ruby 那样只是类名?

使用 JOOQ 的 java.lang.NoSuchMethodError