列出编译期间java编译器所需的所有类

时间:2016-09-11 06:43:29

标签: java plugins compilation bytecode

TL; DR
我正在寻找javac插件API,它允许我记录Java编译器为特定源文件所需的所有类。

更多背景信息:
我正在编写一个工具,可以从Maven迁移到Bazel,其中一个挑战(和机遇)允许Bazel允许,并从中获得更精细的粒度“模块”。另外,依赖关系对于编译类路径是不可传递的。

我正在尝试构建代码的依赖关系图,并在源代码上使用字节码和启发式方法(对于常量,导入等)但是偶然发现了我担心的边缘情况,只能是通过使用编译器插件解决。

鉴于类Foo中的方法Concrete接受扩展SomeInterface的接口ParentInterfacejavac同时需要SomeInterface和{{}虽然ParentInterface没有出现在字节码或源代码中,但在编译类路径中却没有出现。

这在ParentInterface中得到解决,因为依赖关系 相对于编译类路径是传递的,但是我想避免这种情况,因为这大大扩展了类路径(主要是关于源的有趣)依赖性和构建触发)。

我正在尝试查看是否可以使用compiler plugins来识别编译器对给定源文件所需的所有类。这将对我有所帮助,因为我可以运行我的maven构建一次以收集信息,然后根据此信息生成图表。问题是我对API有点失落。

谢谢!

1 个答案:

答案 0 :(得分:0)

那么,编译所需的类是传递的问题。所以,除非你在同一个模块中提取所有这些,否则无法在非传递依赖系统上映射它。

你最终得到的是一个图,其中节点是类,A和B之间的边描绘了A在B中使用。现在每个可以从A到达的类需要处于A的依赖关系。你应该能够将模块构建为连接的子图。

因此,对于您的示例,在分析Concrete之后,您将分析SomeInterface,然后分析ParentInterface。您可以随意构建直接依赖关系图,并自己计算传递依赖关系。

当您自己解决传递性时,除了字节码分析(例如通过ASM)之外,无需执行任何操作来查找所需的类。在编译中将丢失的唯一依赖是未使用的导入,可以将其删除(并且许多java样式指南甚至说它必须被删除)。

PS:在不知道bazel的情况下,这听起来像是在为小模块做出贡献。