【问题标题】:Transitive References In JavaJava 中的传递引用
【发布时间】:2025-12-18 23:05:01
【问题描述】:

tldr; 是什么使得有必要在构建路径中包含传递引用?

说明

我尝试分析一些使用 Eclipse 工作区编译的 Java 源代码。工作区中有很多项目。

我尝试检测项目之间未使用的引用。

我的第一个方法是遍历所有项目并从 .classpath 文件中获取所有引用,然后分析同一项目中的所有 .java 文件。如果 .java 文件具有来自另一个项目的 import 语句,则需要对该另一个项目的引用。 这样我在类路径中发现了一些没有“理由”的引用。

但是当我删除这些引用时,构建失败了。一种这样的情况是,如果引用的类是扩展来自第三个项目的类。该项目被传递引用,需要在构建路径中。

我想知道还有哪些其他类型的关系(继承除外)会导致类路径中的传递引用? 那么多个继承层,每个继承类位于另一个项目中呢?

【问题讨论】:

  • 您的项目是否使用了 DLL、Spring XML 配置、Java 反射或任何其他会阻止从纯源代码分析中实现此目标的方面?
  • 如果两个项目中的两个类在同一个包中,只看import语句是找不到它们之间的依赖关系的。
  • @ProgrammersBlock 我不明白。我做纯源代码分析。
  • @NickL 正确。这是另一个需要考虑的情况。

标签: java reference dependencies classpath transitive-dependency


【解决方案1】:

什么是必要的?

Java 编译的强制规则使其成为必要。 Java 需要知道代码域中的内容以验证是否遵循规则。域是类路径中的一组 jar 文件。 如果你实现了一个接口,非抽象实现类或者实现一个接口的类的非抽象子类需要实现这个接口。需要满足覆盖注释。从代码角度和人类角度来看,对其他方法的引用需要是可见的。如果方法使用不同类或接口中的方法,则调用类需要知道该方法的签名。

我将如何处理它?

我将使用“分类器”来指代类和接口。 您希望从一组已知的已验证分类器和已知的未验证分类器开始。
从已知的未验证分类器开始是目标项目中的所有分类器,并且已知的验证分类器为空。

遍历每个未验证的分类器并识别任何未知的分类器,并将它们添加到未验证的分类器集中。

验证当前未验证的分类器是否在类路径上。未找到则出错。

将已处理的分类器从未验证移动到已验证。

重复此过程,直到所有分类器都得到验证。

使用的分类器包括字段类型、方法返回类型、方法参数类型、参数中的变量类型、扩展类、实现的接口、注释,在某些情况下还包括 Javadoc 引用。根据您的项目规则,仅通过导入可能会遗漏一些事情。接口可能在同一个包中,但来自不同的项目。

为什么反射和 Spring-configuration 需要超出范围?

此类操作使用基于文本的交接来完成代码。反射可以使用字符串“Package.classname”创建一个类,而不会被标识为“使用的类”。这些概念将需要超出纯源代码分析或字节码分析范围的额外处理。

如果您想深入了解,Java 虚拟机规范可以让您更深入地了解类文件需要运行什么。特别是 Java 10 规范中的“4. 类文件格式”和“5. 加载、链接和初始化”。 https://docs.oracle.com/javase/specs/

【讨论】:

  • 回想起来,“使用的分类器”可能还需要类实现中的每个方法调用,因为类文件在字节码中记录了源分类器。意思是如果你有 A.b().c().d();那么即使没有为它们创建变量或字段,也需要考虑 b() 和 c() 的返回类型。
  • 感谢该算法。但是我想知道什么情况会导致传递依赖(或未声明的导入语句),因为我不想构建编译器。
【解决方案2】:

给定

  • 具有引用项目 B 中的 ClassB 的 ClassA 的 ProjectA
  • 带有 ClassC 的第三个 ProjectC

在这些情况下,您需要从 projectA 引用 ProjectC

  • 如果 ClassB 从 classC 继承/实现,并且 ClassA 从 ClassB 调用方法。
  • 如果 ClassA 调用(!)来自 ClassB 的方法,该方法具有包含 ClassC(参数或返回值)的签名(对于异常也是如此!)

此外,并非所有 ProjectA 的引用都可以通过查看 ClassA 的导入语句找到。

  • 如果 ClassA 使用 ClassC 并且与 ClassA 位于同一个包中,则 ClassC 不会在 ClassA 中列为导入。
  • 如果 ClassA 按其全名(包括包名)使用 ClassC,则不会创建 Import 语句。

【讨论】: