java Maven发布插件:指定java编译器版本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3638399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:46:41  来源:igfitidea点击:

Maven release plugin: specify java compiler version

javamaven-2maven-release-plugin

提问by IceGras

I have this project made of multiple jars and war to make an ear. I build everything in snapshot and it works great. Then I made a release for every single project and saw that the jars and the war were slightly different in size than the snapshot ones.

我有这个项目由多个罐子和War组成。我在快照中构建了所有内容,并且效果很好。然后我为每个项目发布了一个版本,看到 jars 和 war 的大小与快照的略有不同。

Comparing file to file I realized that the .class files were all there, but slightly larger or bigger, nothing more than 40 bytes generally.

比较文件与文件,我意识到 .class 文件都在那里,但略大或略大,一般不超过 40 个字节。

I force compilation to use java 1.5 using this tag in Maven:

我在 Maven 中使用这个标签强制编译使用 java 1.5:

<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>

I use this tag for the release plugin:

我将此标签用于发布插件:

<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>

Could it be that the release plugin is compiling in 1.6 or other, explaining the classes size difference ? If so can I make the release plugin compile in 1.5 ?

可能是发布插件在 1.6 或其他版本中编译,解释了类大小差异?如果是这样,我可以在 1.5 中编译发布插件吗?

Thanks for your input.

感谢您的输入。

回答by Lucas

--- SPOILER ALERT ---

--- 剧透警告---

The short answer is that in order to compile source to an older version, you need to supply both the -sourceoption as well as the -bootclasspath. See this article. And if you want to compile source to a newer version, you need to set <source>, <target>, <compilerVersion>, <fork>, and <executable>on the compiler plugin, andset <jvm>on the surefire plugin...

简短的回答是,为了将源代码编译为旧版本,您需要同时提供-source选项和-bootclasspath. 请参阅这篇文章。如果你想编译源到新的版本,你需要设置<source><target><compilerVersion><fork>,和<executable>编译器插件,设置<jvm>在万无一失的插件...

And now for the story...

而现在的故事...

I ran into the same problem. It turns out that compiling a previous version may not be as easy as setting <source>and <target>. My specific case is that I have a Java 1.7 JDK and I my class has an incompatibility with 1.7 (they added a new method to an interface that I am implementing). When I tried to compile it, the compiler gave me an error message stating that I had not implemented the interface method. Anyway, I tried setting the compiler plugin:

我遇到了同样的问题。事实证明,编译以前的版本可能不像设置<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>

but when I ran the build, I got the same error. So I ran maven in debug and saw this:

但是当我运行构建时,我遇到了同样的错误。所以我在调试中运行了 maven 并看到了这个:

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

Note that the ... is put in place of actual arguments for the sake of brevity

请注意,为简洁起见,将 ... 代替实际参数

in the output. The message starting with -dis the actual full compile argument list. So, if you remove the -nowarnflag and paste the rest after javacon the command line you can see the actual output from the compiler:

在输出中。以 开头的消息-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

This prints out the handy-dandy warning bootstrap class path not set in conjunction with -source 1.6. A little googling on that turns up this articlewhich states:

这会打印出没有与 -source 1.6 一起设置的方便的警告引导程序类路径。在谷歌上搜索一下就会出现这篇文章,其中指出:

To use javac from JDK N to cross-compiler to an older platform version, the correct practice is to:

  • Use the older -source setting.
  • Set the bootclasspath to compile against the rt.jar (or equivalent) for the older platform.

If the second step is not taken, javac will dutifully use the old language rules combined with new libraries, which can result in class files that do not work on the older platform since references to non-existent methods can get included.

要使用 JDK N 中的 javac 交叉编译器到旧平台版本,正确的做法是:

  • 使用较旧的 -source 设置。
  • 将引导类路径设置为针对旧平台的 rt.jar(或等效文件)进行编译。

如果不采取第二步,javac 将尽职尽责地使用旧的语言规则与新的库相结合,这可能导致类文件在旧平台上不起作用,因为可能包含对不存在的方法的引用。

Now referencing the maven documentation for the compiler plugingives:

现在参考编译器插件的 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>

Which you can then combine with your earlier configuration to get:

然后您可以将其与您之前的配置结合以获得:

  <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>

And now you just need to make the ${java.home}variable available to your mvn (through -D system properties, or through plain old environment variables, or you could get really fancy and stuff it in a java 6 profile in your user settings).

现在您只需要让${java.home}变量对您的 mvn 可用(通过 -D 系统属性,或通过普通的旧环境变量,或者您可以非常喜欢并将其填充到您的用户设置中的 java 6 配置文件中)。

Now just run your build and go grab a cold beer while it chugs away...

现在只需运行您的构建并在它突然消失时去喝一杯冰镇啤酒......

---- EDIT ----

- - 编辑 - -

One last thing... Including rt.jar in your bootclasspath is alwaysrequired, however, I discovered that more may be needed on a case by case basis. I had to include jce.jar (in the same directory as rt.jar) because my app was doing crypto work.

最后一件事......在你的引导类路径中包含 rt.jar总是需要的,但是,我发现根据具体情况可能需要更多。我必须包含 jce.jar(与 rt.jar 位于同一目录中),因为我的应用程序正在执行加密工作。

---- EDIT 2 ----

---- 编辑 2 ----

For grins, I tried it the other direction. Instead of running maven with java 7 compiling for java 6, I ran maven with java 6 compiling for java 7. The first attempt is pretty straight forward:

对于笑容,我尝试了另一个方向。我没有用 java 7 编译 java 6 运行 maven,而是运行 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>

Basically, I set my <source>and <target>to 1.7, but that clearly would not be enough because 6 cant compile 7 code. So back to the compiler plugin, there is actually an example pagedescribing what needs to be done. Namely, you need to <fork>off a new process using the java 7 <executable>. So now I think I'm all set. Time to fire up the build...

基本上,我将我的<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] ------------------------------------------------------------------------

What the heck is UnsupportedClassVersionError? A closer look tells us its the maven-surefire-plugin that is failing. So I try just mvn compileand sure enough I get a success as the surefire plugin never fired up. So I run mvn -X packageand notice this gem:

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"

Ok, so its running java 6. Why? The documentation for surefire gives this:

好的,所以它运行的是 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.

Since we ran mvn with a java 6 VM its forking a java 6 VM for its unit tests. So setting this option appropriately:

由于我们使用 java 6 VM 运行 mvn,因此它为单元测试创​​建了一个 java 6 VM。所以适当地设置这个选项:

  <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>

And firing up the build...

并启动构建...

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

回答by BenjaminLinus

You can verify the version a class is compiled for by using the javap utility included with the JDK. From the command line:

您可以使用 JDK 中包含的 javap 实用程序来验证为类编译的版本。从命令行:

javap -verbose MyClass

In the output of javap look for "minor version" and "major version" about ten lines down.

在 javap 的输出中查找大约十行以下的“次要版本”和“主要版本”。

Then use this table:

然后使用这个表:

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

The .class size difference may be due to compile version but also may be due to other compile options like compiling with debug information (line numbers in stacktraces).

.class 大小差异可能是由于编译版本,但也可能是由于其他编译选项,例如使用调试信息(堆栈跟踪中的行号)进行编译。

回答by Pascal Thivent

Could it be that the release plugin is compiling in 1.6 or other, explaining the classes size difference ?

可能是发布插件在 1.6 或其他版本中编译,解释了类大小差异?

Can't be IMO. The Maven Release Plugin doesn't compile anything, it just triggers a phase that will itself trigger the compilephase and the Maven Compiler Plugin. In other words, the Maven Compiler Plugin and its settings will be used.

不可能是海事组织。Maven Release Plugin 不编译任何东西,它只是触发一个阶段,该compile阶段本身会触发阶段和 Maven Compiler Plugin。换句话说,将使用 Maven Compiler Plugin 及其设置。

You can use the following commands to control what is happening exactly:

您可以使用以下命令来准确控制正在发生的事情:

mvn help:active-profiles -Prelease

to check profiles. And

检查配置文件。和

mvn help:effective-pom -Prelease

to check the effective pom.

检查有效的pom。

回答by Praveen

Just a note, if a wrong version is picked up, you will get an error something like

请注意,如果选择了错误的版本,您将收到类似的错误

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

During maven release, maven release plugin (sets/defaults to) the compiler version 1.5. To ensure it picks up the correct version specify the properties.

在 maven 发布期间,maven 发布插件(设置/默认为)编译器版本 1.5。为确保它选择正确的版本,请指定属性。

<properties>
 <maven.compiler.source>1.7</maven.compiler.source>
 <maven.compiler.target>1.7</maven.compiler.target>
</properties>