【问题标题】:Listing all classes the java compiler needs during compilation列出 java 编译器在编译期间需要的所有类
【发布时间】:2017-01-18 21:37:21
【问题描述】:

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

更多上下文:
我正在编写一个从Maven 迁移到Bazel 的工具,其中一个挑战(和机遇)是Bazel 允许并受益于更细粒度的“模块”。此外,依赖项对于编译类路径是不传递的。

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

给定类Concrete中的一个方法Foo,它接受一个扩展ParentInterface的接口SomeInterface,那么javac在编译类路径中需要SomeInterfaceParentInterface,尽管ParentInterface不需要出现在字节码或源代码中。

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

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

谢谢!

【问题讨论】:

  • 您可以检查 SomeInterface 以查看它是否需要 ParentInterface。您可以使用反射或字节码分析。如果这听起来太难了,我可以向您保证,尝试使用编译器获取此信息要困难 10 倍。
  • @PeterLawrey 谢谢!反射可能对我没有帮助,因为我对构建时间感兴趣,但字节码可以工作。问题是,只有在某些情况下,我才需要父母,而您的方法要求要么学习所有这些边缘案例,要么将范围扩展到所有辅助类型及其祖先(这当然可以是第三方,这会使它复杂化进一步)...
  • 是的。您还需要在运行时通过反射获得的任何类可能更难确定。
  • 考虑在 kythe Discussion 上提出问题,他们或许可以提供帮助。 groups.google.com/forum/#!forum/kythe

标签: java plugins compilation bytecode


【解决方案1】:

好吧,编译需要哪些类的问题是可传递的。因此,除非您将所有这些都拉到同一个模块中,否则无法将其映射到非传递依赖系统上。

你最终得到的是一个图,其中节点是类,A 和 B 之间的一条边表示 A 在 B 中使用。现在从 A 可访问的每个类都需要依赖于 A。你应该能够将模块构建为连接的子图。

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

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

PS:在不了解 bazel 的情况下,这听起来像是您正在为小模块开辟道路。

【讨论】:

  • 您所描述的是完全传递闭包,这不是我想要的。我想要最小的传递闭包,可以通过以下两种方式之一来实现: 1. 编译器插件列出所有需要的类。 2. 了解需要的依赖类型,并只为那些做准备。在 Scala 中,我使用的是前一种方法
猜你喜欢
  • 2018-09-05
  • 2013-06-19
  • 1970-01-01
  • 2017-02-18
  • 2010-10-06
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多