Ohhnews

分类导航

$ cd ..
Baeldung原文

如何修复pom.xml文件中缺失com.sun:tools:jar构件错误

#maven#java#jdk#依赖管理#pom.xml

[LOADING...]

1. 概述

在处理较旧的 Java 仓库时,尤其是为 Java 8 或更早版本创建的 Maven 项目,Eclipse 可能会报告与 com.sun:tools 依赖相关的错误:

Missing artifact com.sun:tools:jar:1.6

类似地,Ant 构建可能会失败,并给出类似消息:

Unable to locate tools.jar

在命令行中,Maven 会报告缺失的依赖及其预期路径:

[ERROR] Could not resolve dependencies for project ...
[ERROR] dependency: com.sun:tools:jar:1.8 (system)
[ERROR] Could not find artifact com.sun:tools:jar:1.8 at specified path /opt/jdk-21/../lib/tools.jar

在本教程中,我们将研究 com.sun:tools:jar 工件为何可能缺失,以及如何解决该问题。

2. 理解问题

较旧的库和 Maven 项目有时会将 tools.jar 声明为系统依赖项:

$ xml
<dependency>
    <groupId>com.sun</groupId>
    <artifactId>tools</artifactId>
    <version>1.8</version>
    <scope>system</scope>
    <systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>

在 JDK 8 上,java.home 是 JDK 的 jre 目录,因此 ${java.home}/../lib/tools.jar 指向 JDK 路径 lib/tools.jar。相反,独立的 JRE 实例中没有此文件。

与普通 Maven 依赖不同,作用域为 system 的依赖并不来自 Maven Central 或其他仓库。 相反,Maven 期望该 JAR 存在于 systemPath 指定的位置。

在 JDK 8 及更早版本中,tools.jar 是 JDK 安装的一部分,包含 Java 开发工具使用的类。

3. 使用 JRE 而不是 JDK

独立的 Java 8 JRE 不包含 tools.jar。

首先确认 Maven 使用的是哪个 Java 安装:

$ bash
mvn -version

较新的 Maven 版本会将运行时路径标记为 runtime:,而较旧版本使用 Java home:。类似 jre1.8.0_301 的独立 JRE 路径说明可能存在问题。另一方面,对于 JDK 8,jdk1.8.0_301/jre 应该是正常的。

要纠正这种情况,我们可以设置 JAVA_HOME 为相关 JDK 目录。下面看一个 Linux 或 macOS 上的示例:

$ bash
export JAVA_HOME=/opt/jdk1.8.0_301

在这种情况下,JAVA_HOME 指向 JDK 根目录,而不是其 bin 目录。

4. IDE 使用了错误的 Java 安装

在 Eclipse 中,我们可以先在 Preferences > Java > Installed JREs 下检查已配置的 Java 安装,并确保选择了合适的 JDK。对于支持 Java 8 的较旧 Eclipse 版本,我们可以通过 eclipse.ini 中的 -vm 选项显式配置 Eclipse 的 JVM:

[...]
-vm
C:\jdk1.8.0_301\bin\javaw.exe
-vmargs
[...]

重启 Eclipse 后,我们更新或重新导入 Maven 项目。值得注意的是,各个 Maven 运行配置可以有自己的 JRE 设置。

5. 使用 JDK 9 或更高版本构建

从 JDK 9 开始,tools.jar 不再存在。公共工具 API 仍可通过 jdk.compiler(javac 和 Compiler Tree API)以及 jdk.attach(Attach API)等模块使用,而无需额外的 JAR 依赖。

Maven 还会打印一条警告,但这里建议的修复方式是错误的:

[WARNING] 'dependencies.dependency.systemPath' for com.sun:tools:jar refers to a non-existing file /opt/jdk-21/../lib/tools.jar. Please verify that you run Maven using a JDK and not just a JRE.

由于即使完整的 JDK 9 或更高版本也没有 tools.jar,因此切换到 JDK 并不能解决该问题。

对于同时支持 JDK 8 和更新版本的项目,我们可以将该依赖项移入仅适用于 JDK 8 的 profile:

$ xml
<profiles>
    <profile>
        <id>jdk8-tools</id>
        <activation>
            <jdk>1.8</jdk>
        </activation>
        <dependencies>
            <dependency>
                <groupId>com.sun</groupId>
                <artifactId>tools</artifactId>
                <version>1.8</version>
                <scope>system</scope>
                <systemPath>${java.home}/../lib/tools.jar</systemPath>
            </dependency>
        </dependencies>
    </profile>
</profiles>

如果第三方库、Maven 插件或框架声明了 com.sun:tools,我们应将该组件升级到与较新 Java 版本兼容的版本。

6. 排除过时依赖

要定位该声明,我们检查有效 POM:

$ bash
mvn help:effective-pom

这会包含来自项目、其父项目以及活动 profile 的声明,但不包含传递依赖。对于传递依赖,我们使用另一个命令:

$ bash
mvn dependency:tree -Dincludes=com.sun:tools

如果较新的 JDK 已经提供了该库所需的功能,并且对 tools.jar 的依赖已经过时,我们或许可以将其排除:

$ xml
<dependency>
    <groupId>com.example</groupId>
    <artifactId>legacy-library</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.sun</groupId>
            <artifactId>tools</artifactId>
        </exclusion>
    </exclusions>
</dependency>

仅当该库能与目标 JDK API 正常工作时,此解决方案才适用。 否则,Maven 错误可能会被编译错误或运行时错误取代。

7. 避免手动处理 tools.jar 的变通方案

复制或手动安装 tools.jar 会使构建依赖于本地修改,并导致开发机器与 CI 环境之间的行为不一致。Maven 支持系统作用域依赖项,但不鼓励使用它们。

8. 结论

本文中,我们探讨了 Missing artifact com.sun:tools:jar 和 Unable to locate tools.jar 错误。

对于 Java 8 及更早版本,该问题通常意味着 Maven 或 IDE 使用的是 JRE,而不是所需的 JDK,因此配置 JAVA_HOME 和 IDE 的 JVM 即可解决该问题。从 Java 9 开始,tools.jar 不再存在,因此需要升级、移除那些依赖它的旧依赖项,或使用合适的旧版 JDK 进行构建。