Плагин релиза Maven: укажите версию компилятора Java - PullRequest
15 голосов
/ 03 сентября 2010

У меня есть этот проект, сделанный из нескольких банок и войны, чтобы сделать ухо. Я строю все в снимке, и он прекрасно работает. Затем я сделал релиз для каждого отдельного проекта и увидел, что банки и война немного отличаются по размеру от снимков.

Сравнивая файл с файлом, я понял, что все файлы .class были там, но немного больше или больше, обычно не более 40 байт.

Я заставляю компиляцию использовать Java 1.5, используя этот тег в Maven:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target> 
                </configuration>

Я использую этот тег для плагина релиза:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-release-plugin</artifactId>
    <version>2.0</version>
    <configuration>
        <releaseProfiles>release</releaseProfiles>
        <goals>deploy</goals>
    </configuration>
</plugin>

Может ли плагин релиза скомпилироваться в 1.6 или другой, объясняя разницу в размерах классов? Если да, могу ли я сделать плагин релиза скомпилированным в 1.5?

Спасибо за ваш вклад.

Ответы [ 4 ]

19 голосов
/ 13 июля 2012

--- SPOILER ALERT ---

Краткий ответ: для того, чтобы скомпилировать исходный код в более старую версию, вам необходимо указать и параметр -source.как -bootclasspath.См. эту статью .И если вы хотите скомпилировать исходный код в более новую версию, вам нужно установить <source>, <target>, <compilerVersion>, <fork> и <executable> в плагине компилятора, и set <jvm> на плагине surefire ...

А теперь для истории ...

Я столкнулся с той же проблемой.Оказывается, компиляция предыдущей версии может быть не такой простой, как установка <source> и <target>.Мой конкретный случай - у меня Java 1.7 JDK, и у моего класса несовместимость с 1.7 (они добавили новый метод в интерфейс, который я реализую) .Когда я пытался скомпилировать его, компилятор выдал мне сообщение об ошибке, в котором говорилось, что я не реализовал метод интерфейса.В любом случае, я попытался установить плагин компилятора:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
      <encoding>UTF-8</encoding>
    </configuration>
  </plugin>

, но когда я запустил сборку, я получил ту же ошибку.Поэтому я запустил maven в режиме отладки и увидел следующее:

[INFO] [DEBUG] Command line options:
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8

Обратите внимание, что ... для краткости вместо фактических аргументов ставится ... 1034 *

inвыход.Сообщение, начинающееся с -d, является фактическим полным списком аргументов компиляции.Таким образом, если вы уберете флаг -nowarn и вставите остальное после javac в командной строке, вы сможете увидеть фактический вывод компилятора:

javac -d C:\... -target 1.6 -source 1.6 -encoding UTF-8
warning: [options] bootstrap class path not set in conjunction with -source 1.6

Это выводит на экран предупреждение об удобстве Путь к классу начальной загрузки не задан в сочетании с -source 1.6 .Немного прибегая к помощи, которая обнаруживает эту статью , в которой говорится:

Чтобы использовать javac из JDK N для кросс-компиляции на более старую версию платформы, правильная практика заключается в следующем:

  • Используйте более старую настройку -source.
  • Установите bootclasspath для компиляции с rt.jar (или эквивалентным) для более старой платформы.

Есливторой шаг не сделан, javac будет должным образом использовать старые языковые правила в сочетании с новыми библиотеками, что может привести к тому, что файлы классов не будут работать на более старой платформе, поскольку могут быть включены ссылки на несуществующие методы.

Теперь ссылаясь на , документация maven для плагина компилятора дает:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.5.1</version>
    <configuration>
      <compilerArguments>
        <verbose />
        <bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
      </compilerArguments>
    </configuration>
  </plugin>

, которую затем можно объединить с более ранней конфигурацией, чтобы получить:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
      <encoding>UTF-8</encoding>
      <bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
    </configuration>
  </plugin>

А теперь вам просто нужно сделать переменную ${java.home} доступной для вашего mvn (через системные свойства -D, или через простые старые переменные окружения, или вы можете получить действительно модные вещи и прочее)это в профиле java 6 в ваших пользовательских настройках).

Теперь просто запустите сборку и возьмите холодное пиво, пока оно выпрыгивает ...

---- EDIT ----

И еще одна вещь ... Включение rt.jar в путь начальной загрузки всегда требуется, однако я обнаружил, что в каждом конкретном случае может потребоваться больше.Мне пришлось включить jce.jar (в тот же каталог, что и rt.jar), потому что мое приложение выполняло криптографическую работу.

---- EDIT 2 ----

Для ухмылок,Я попробовал это в другом направлении.Вместо запуска maven с компиляцией java 7 для java 6, я запустил maven с компиляцией java 6 для java 7. Первая попытка довольно проста:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.5.1</version>
    <configuration>
      <source>1.7</source>
      <target>1.7</target>
      <fork>true</fork>
      <verbose>true</verbose>
      <compilerVersion>1.7</compilerVersion>
      <executable>${JAVA_7_HOME}/bin/javac</executable>
      <encoding>UTF-8</encoding>
    </configuration>
  </plugin>

По сути, я установил <source> и <target> до 1,7, но этого явно недостаточно, потому что 6 не могут скомпилировать 7 кодов.Итак, вернемся к плагину компилятора, на самом деле пример страницы , описывающей, что нужно сделать.А именно, вам нужно <fork> отключить новый процесс с использованием Java 7 <executable>.Так что теперь я думаю, что все готово.Время запустить сборку ...

C:\Projects\my-project>mvn package
...
Caused by: java.lang.UnsupportedClassVersionError: mypackage.StupidTest : Unsup
ported major.minor version 51.0
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

Какого черта UnsupportedClassVersionError?Более внимательный взгляд говорит нам о том, что это maven-surefire-plugin, который не работает.Поэтому я пробую просто mvn compile и, конечно же, получаю успех, так как плагин surefire никогда не запускается.Итак, я запускаю mvn -X package и замечаю этот драгоценный камень:

Forking command line: cmd.exe /X /C ""C:\Program Files\Java\jdk1.6.0_29\jre\bin\
java" -jar C:\Projects\my-project\target\surefire\surefirebooter2373372991878002
398.jar C:\Projects\my-project\target\surefire\surefire1861974777102399530tmp C:
\Projects\my-project\target\surefire\surefire4120025668267754796tmp"

Хорошо, так что работает Java 6. Почему?Документация для безошибочного дает это:

jvm:
Option to specify the jvm (or path to the java executable) to use with the forking 
options. For the default, the jvm will be a new instance of the same VM as the one 
used to run Maven. JVM settings are not inherited from MAVEN_OPTS.

Поскольку мы запустили mvn с виртуальной машиной Java 6, она создала виртуальную машину Java 6 для своих модульных тестов. Поэтому, установив эту опцию соответствующим образом:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12</version>
    <configuration>
      <jvm>${JAVA_7_HOME}/bin/java</jvm>
    </configuration>
  </plugin>

И запустить сборку ...

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
1 голос
/ 04 сентября 2010

Вы можете проверить версию, для которой скомпилирован класс, с помощью утилиты javap, включенной в JDK. Из командной строки:

javap -verbose MyClass

В выводе javap ищите «минорная версия» и «основная версия» примерно на десять строк ниже.

Тогда используйте эту таблицу:

major       minor       Java platform version
45          3           1.0
45          3           1.1
46          0           1.2
47          0           1.3
48          0           1.4
49          0           1.5
50          0           1.6

Разница в размере .class может быть связана с версией компиляции, но также может быть связана с другими параметрами компиляции, такими как компиляция с отладочной информацией (номера строк в трассировках стека).

0 голосов
/ 24 августа 2017

Просто обратите внимание: если выбрана неправильная версия, вы получите сообщение об ошибке, похожее на

xxxx is not supported in -source 1.5
[ERROR] (use -source 7 or higher to enable yyyy)

Во время выпуска maven плагин maven выпускает (устанавливает / по умолчанию) версию компилятора 1.5.Чтобы убедиться, что выбрана правильная версия, укажите свойства.

<properties>
 <maven.compiler.source>1.7</maven.compiler.source>
 <maven.compiler.target>1.7</maven.compiler.target>
</properties>
0 голосов
/ 04 сентября 2010

Может ли плагин релиза компилироваться в 1.6 или другой, объясняя разницу в размерах классов?

Не может быть ИМО.Плагин Maven Release ничего не компилирует, он просто запускает фазу, которая сама по себе запускает фазу compile и плагин Maven Compiler.Другими словами, будет использоваться плагин Maven Compiler и его настройки.

Вы можете использовать следующие команды для точного управления происходящим:

mvn help:active-profiles -Prelease

для проверки профилей.И

mvn help:effective-pom -Prelease

для проверки эффективного пом.

...