【问题标题】:Required Java version of Maven Dependency?需要 Java 版本的 Maven 依赖项?
【发布时间】:2016-09-30 19:40:08
【问题描述】:

我使用 Maven 开发和构建了我的 Java 应用程序。我需要支持 Java 1.6,所以我使用以下属性:

<maven.compiler.target>1.6</maven.compiler.target>
<maven.compiler.source>1.6</maven.compiler.source>

不过,当我运行应用程序时,我收到“Unsupported major.minor version”错误,我怀疑我的一个依赖 jar 是用比我需要支持的版本更新的 Java 版本编译的。

我的问题:

  1. 这可能吗?我以为 Maven 会处理这种依赖版本问题。

  2. 有没有一种简单的方法可以找出我所有依赖项的次要/主要版本? (例如,如果它可以在mvn dependency:tree 时显示出来,那就太棒了。)

【问题讨论】:

  • 你能发布你的整个 maven 文件吗?
  • 有一些我不想在 SO 上披露的东西,例如证书信息。但这里是相关部分的精简版:pastebin.com/BE7yDbSV
  • 看来 Jersey 2.6 是在 java 6 中编译的最后一个版本。之后是 java 7。参考:jersey.java.net/documentation/latest/…
  • 好的。我认为杰克逊也是一个问题。我也可以手动挖掘这些信息。不过,这并没有回答我的两个问题。
  • 我发现 jackson 2.3 在 java 6 中的编译位置。我在 2.4 上找不到任何确定的东西。至于你的问题,1)maven 不会自动降级,你必须自己指定。 2)我不知道找出主要/次要版本依赖关系的好方法。但这并不意味着不存在。

标签: java maven


【解决方案1】:

问题在于每个依赖项(维护者)都可以自行决定使用哪个 java 版本进行编译(1.5、1.6、1.7、1.8 等),因此这无法通过 Maven 解决。但是您可以确保您不使用与您希望拥有的 Java 版本不同的依赖项。

这可以通过使用Maven Enforcer Pluginextra-enforcer-rules 来执行:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>1.4.1</version> <!-- find the latest version at http://maven.apache.org/plugins/maven-enforcer-plugin/ -->
        <executions>
          <execution>
            <id>enforce-bytecode-version</id>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <enforceBytecodeVersion>
                  <maxJdkVersion>1.6</maxJdkVersion>
                  <excludes>
                    <exclude>org.mindrot:jbcrypt</exclude>
                  </excludes>
                </enforceBytecodeVersion>
              </rules>
              <fail>true</fail>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>extra-enforcer-rules</artifactId>
            <version>1.0-beta-5</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

如果您的依赖项是使用与您想要的不同版本的 JDK 编译的,这将破坏您的构建。

【讨论】:

  • 这很好。我假设这些规则也适用于传递依赖?
  • 文档摘录:This rule checks the dependencies transitively and fails if any class of any dependency is having its bytecode version higher than the one specified.mojo.codehaus.org/extra-enforcer-rules/…
  • 我在谷歌上搜索了一下才到这里。非常感谢。
  • 可以用mvn validate调用
  • 排除 jbcrypt 是否有特殊原因?
【解决方案2】:

回答你的两个问题:

是的,这是可能的。查看docs&lt;maven.compiler.target&gt;&lt;maven.compiler.source&gt; 属性只是告诉Maven 使用哪个版本的javac 来编译你的 项目。我引用,供您参考:

注意:仅设置 target 选项并不能保证您的 代码实际上在具有指定版本的 JRE 上运行。陷阱是 意外使用仅存在于后来的 JRE 中的 API,这将 使您的代码在运行时因链接错误而失败。为了避免这种情况 问题,您可以配置编译器的引导类路径以匹配 目标 JRE 或使用 Animal Sniffer Maven Plugin 来验证您的 代码不使用非预期的 API。

Unsupported major.minor version错误后面的magic number实际上告诉了类文件兼容的JRE版本:

J2SE 8 = 52,
J2SE 7 = 51,
J2SE 6.0 = 50,
J2SE 5.0 = 49,
JDK 1.4 = 48,
JDK 1.3 = 47,
JDK 1.2 = 46,
JDK 1.1 = 45

我不知道是否有一种简单的方法可以告诉项目中所有依赖项(和传递依赖项)的主要/次要版本。

更新:虽然我以前没有使用过它,但我想知道 Animal Sniffer Maven plugin 将有助于嗅出您的依赖项的主要/次要版本。

【讨论】:

  • 不幸的是,动物嗅探器仅适用于您自己编写的代码,而不适用于依赖项。基于 Maven 中的依赖项是一个二进制工件,它已使用任何版本编译,您无法在构建中设置编译器版本以强制依赖项的版本。
猜你喜欢
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2015-05-13
  • 2016-09-18
  • 2013-06-20
  • 2022-10-19
相关资源
最近更新 更多