Требуемая Java-версия зависимости Maven?

#java #maven-3

#ява #мавен #maven

Вопрос:

Я разработал и построил свое Java-приложение, используя Maven. Мне нужно поддерживать Java 1.6, поэтому я использую следующие свойства:

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

Тем не менее, когда я запускаю приложение, я получаю ошибку «Неподдерживаемая основная.второстепенная версия», и я подозреваю, что одна из моих банок зависимостей скомпилирована с версией Java, более новой, чем та, которую мне нужно поддерживать.

Мои вопросы:

  1. Возможно ли это вообще? Я думал, что Maven позаботится о такого рода проблемах с версиями зависимостей.

  2. Есть ли простой способ узнать младшую / основную версию всех моих зависимостей? (Было бы здорово, если бы это можно было показать, например, при выполнении mvn dependency:tree .)

Комментарии:

1. Можете ли вы опубликовать весь свой файл maven?

2. Есть некоторые вещи, которые я бы предпочел не раскрывать на SO, например, информация о сертификате. Но вот урезанная версия соответствующих частей: pastebin.com/BE7yDbSV

3. Похоже, что Jersey 2.6 была последней версией, скомпилированной на java 6. После этого это была java 7. Ссылка: jersey.java.net/documentation/latest /…

4. ОК. Я думаю, что Джексон тоже является проблемой. Я тоже, вероятно, мог бы откопать эту информацию вручную. Однако это не отвечает ни на один из моих двух вопросов.

5. Я нашел, где jackson 2.3 скомпилирован на Java 6. Я не могу найти ничего определенного в 2.4. Что касается ваших вопросов, 1) maven не будет выполнять автоматическое понижение такого рода, вы должны указать это самостоятельно. 2) Я не знаю хорошего способа выяснить зависимости основных и второстепенных версий. Однако это не значит, что его не существует.

Ответ №1:

Проблема в том, что каждая зависимость (сопровождающий) может самостоятельно решить, какая версия Java используется для компиляции (1.5, 1.6, 1.7, 1.8 и т.д.), Так что это не решаемо с помощью Maven. Но вы можете убедиться, что не используете зависимости, которые используют другую версию Java, чем вам хотелось бы иметь.

Это можно обеспечить с помощью плагина Maven Enforcer с помощью дополнительных правил enforcer:

 <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, чем вы хотите иметь.

Комментарии:

1. Это здорово. Я предполагаю, что эти правила применяются и к транзитивным зависимостям?

2. Выдержка из документов: 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 /…

3. Мне потребовалось немного поискать в Google, чтобы добраться сюда. Очень ценится.

4. может быть вызван с mvn validate

5. Есть ли какая — то особая причина для исключения jbcrypt ?

Ответ №2:

Чтобы ответить на ваши два вопроса:

Да, это возможно. Просмотр свойств docs , <maven.compiler.target> и <maven.compiler.source> просто указывает Maven, какую версию javac использовать для компиляции вашего проекта. И я цитирую для вашей справки:

Примечание: Простая установка параметра target не гарантирует, что ваш код действительно выполняется на JRE с указанной версией. Ошибка заключается в непреднамеренном использовании API, которые существуют только в более поздних JRES, что приведет к сбою вашего кода во время выполнения с ошибкой привязки. Чтобы избежать этой проблемы, вы можете либо настроить путь к загрузочному классу компилятора в соответствии с целевой JRE, либо использовать плагин Animal Sniffer Maven, чтобы убедиться, что ваш код не использует непреднамеренные API.

Магическое число после Unsupported major.minor version ошибки фактически указывает версию 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 поможет выявить основную / второстепенную версию ваших зависимостей.

Комментарии:

1. К сожалению, animal sniffer предназначен только для вашего собственного написанного кода, а не для зависимостей. Основываясь на том, что зависимость в Maven является двоичным артефактом, который был скомпилирован с любой версией, вы не можете установить версию компилятора в своей сборке для принудительного использования версий зависимостей.