【问题标题】:Is it possible to ignore runtime imports in Java classpath JARs on compilation?是否可以在编译时忽略 Java 类路径 JAR 中的运行时导入?
【发布时间】:2015-07-18 07:56:36
【问题描述】:

我正在尝试通过 Ant 使用 javac 编译一个大型 Java 项目。这是在装有 Yosemite 操作系统的 Mac 上,使用 Java 8,如果相关的话。

没有详细说明,我的 A 类依赖于 B 类,它包含在第三方库中。第三方 JAR 库 位于 类路径中。我不拥有它的源代码。 B 类显然依赖于 C 类,它在运行时出现在应用程序服务器的类路径中,但在构建期间不存在。

编译失败,提示找不到 C 类。如果我在类路径中包含包含 C 类的服务器 JAR,则构建工作正常。但是,其他开发人员可以在不将服务器 JAR 包含在类路径中的情况下构建项目,如果可以避免的话,我宁愿在构建中不包含服务器 JAR。

下面的模拟 Ant 输出:

compile:
    [javac] Compiling 180 source files to /some/directory/output
    [javac] /some/directory/src/A.java:123: error: cannot access C
    [javac]  return B.build();
    [javac]         ^
    [javac]   class file for C not found
    [javac] 1 error

所以我的问题是:

  1. 有没有办法总是说服 Java 忽略这种类型的运行时依赖?它适用于主要使用 Java 7 的其他开发人员。

  2. 为什么不是每个运行时依赖项都会发生这种情况?我在过去的各种项目中都看到过这种情况,但这从来都不是问题。

【问题讨论】:

  • 那么真的没有什么可以做到这一点吗?我正在考虑修改javac,所以有一个“关闭并构建”标志。在使用 Java 时,我可能花费更多时间试图让编译器满意,而不是实际编写/修复代码。理论上我喜欢类型检查,但在实践中,我认为找出运行时异常比解决编译时依赖关系要快。

标签: java ant dependencies javac


【解决方案1】:

编译器绝对会在编译时尝试查找您“通常”引用的类:(即直接使用类名符号,此后只是“引用”),以捕获以后可能出错的各种事情,并在编译前警告您和/或让您修复它们。

您只有几个选择。

1) 在构建时包含类路径中的依赖项,以便编译器可以找到它们。这是正常的,理智的方式来解决这个问题。你为什么不想这样做呢?

2) 使用反射访问和加载有问题的类,以便它们在运行时显式解析和验证,而不是在类加载时。这通常不是处理事情的好方法。

3)(最好的恕我直言)将您的项目迁移到像 Maven 这样的构建系统,它具有依赖项跟踪并处理“我构建时类路径应该是什么”等所有这些细节。您可以使用“提供" 依赖范围向 Maven 表明您在特定依赖项中引用的类的实际实现不在您的应用程序中,但稍后会提供......(Ivy 也很好,两者都在 Ant 之上构建工作)

如果其他开发人员正在编译引用类 C 的代码,我向您保证,他们的类路径中的某处有一个 C.class。

【讨论】:

  • 问题不在于引用 C 的代码。引用 C 的类是 B,它已经编译并且我只能以二进制 .class 形式使用。我们的代码都没有明确引用 C。我引用了本身引用 C 的二进制类 B。(我实际上是代表另一个开发人员提出这个问题 - 我是另一个可以在没有 C 的情况下构建它的开发人员。在 Java 7 中工作正常.)
  • 我敢打赌,你的类路径中有一个 C.class。 =p
  • 源代码与编译的类无关——编译器不需要引用类的源代码,只需要类文件(如果类文件不存在并且有源代码,它将递归编译)。如果 C 是通过 B 导出的(可能它使用了一个 C 作为方法参数、返回值或非私有字段),编译器还是会想戳 C 看看。
  • 迟到了,但其他开发人员确实安装了 Java 7,并且构建正常进行。这绝对是Java版本问题,但我没有时间尝试重现它。 Java 8 可能在编译期间对类路径条目进行了更深入的挖掘。
猜你喜欢
  • 2011-01-17
  • 2021-09-27
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
  • 2011-08-17
  • 2023-03-04
  • 2015-11-20
  • 2020-01-30
相关资源
最近更新 更多