Especificando a versão java no maven - diferenças entre propriedades e plug-in do compilador

178

Não tenho muita experiência com o maven e, enquanto experimentava o projeto com vários módulos, comecei a me perguntar como posso especificar a versão java para todos os meus módulos filhos no pai maven pom. Até hoje eu estava usando apenas:

<properties>
    <java.version>1.8</java.version>
</properties>

mas, ao pesquisar, descobri que você também pode especificar a versão java no plug-in do compilador maven, assim:

<plugins>
    <plugin>    
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

Em seguida, envolva isso na tag de gerenciamento de plug-ins para permitir o uso de pompons filhos. Portanto, a primeira pergunta é quais são as diferenças entre definir a versão java nas propriedades e no plug-in do compilador maven?

Não consegui encontrar uma resposta clara, mas, no processo de pesquisa, descobri que você também pode especificar a versão java desta maneira:

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

o que sugere que o plugin do compilador existe, mesmo que eu não o declare explicitamente. Executando saídas de pacotes mvn com

maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---

e alguns outros plugins que não declarei. Então, esses plugins são parte padrão e oculta do maven pom? Existem diferenças entre a definição de origem / destino nas propriedades e no elemento de configuração do plugin maven?

Algumas outras perguntas são: qual o caminho a ser usado (e quando, se não forem iguais)? Qual é o melhor para o projeto de vários módulos e o que acontece se a versão java especificada no pom for diferente da versão apontada em JAVA_HOME?

Plebejusz
fonte

Respostas:

288

Como especificar a versão do JDK?

1) <java.version>não é mencionado na documentação do Maven.
É uma especificidade do Spring Boot.
Ele permite definir a versão java de origem e de destino com a mesma versão, como esta, para especificar o java 1.8 para ambos:

<properties>
     <java.version>1.8</java.version>
</properties>   

Sinta-se livre para usá-lo se você usa o Spring Boot.

2) Usando maven-compiler-pluginou maven.compiler.source/ maven.compiler.targetproperties para especificar the sourcee the targetsão equivalentes.

<plugins>
    <plugin>    
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

e

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

são equivalentes de acordo com a documentação do Maven do plug-in do compilador, pois <source>os <target>elementos e na configuração do compilador usam as propriedades maven.compiler.sourcee maven.compiler.targetse elas estão definidas.

fonte

O -sourceargumento para o compilador Java.
O valor padrão é: 1.6.
Propriedade de usuário é: maven.compiler.source.

alvo

O -targetargumento para o compilador Java.
O valor padrão é: 1.6.
Propriedade de usuário é: maven.compiler.target.

Sobre os valores padrão para sourcee target, observe que, desde o 3.8.0compilador maven, os valores padrão foram alterados de 1.5para1.6 .

3) O maven-compiler-plugin 3.6e versões posteriores oferecem uma nova maneira:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>9</release>
    </configuration>
</plugin>

Você também pode declarar apenas:

<properties>
    <maven.compiler.release>9</maven.compiler.release>
</properties>

Mas, no momento, não funcionará, pois a maven-compiler-pluginversão padrão usada não depende de uma versão suficientemente recente.

O releaseargumento Maven transmite release: uma nova opção padrão da JVM que poderíamos passar do Java 9:

Compila na API pública, suportada e documentada para uma versão específica da VM.

Essa maneira fornece uma maneira padrão de especificar a mesma versão para as opções source, the targete bootstrapJVM.
Observe que especificar bootstrapé uma boa prática para compilações cruzadas e não será prejudicial se você também não fizer compilações cruzadas.


Qual é a melhor maneira de especificar a versão do JDK?

A primeira maneira ( <java.version>) é permitida apenas se você usar o Spring Boot.

Para Java 8 e abaixo:

Sobre as duas outras maneiras: avaliar as propriedades maven.compiler.source/ ou usar as , você pode usar uma ou outra. Isso não muda nada nos fatos, pois, finalmente, as duas soluções contam com as mesmas propriedades e o mesmo mecanismo: o plug-in do compilador principal do maven. maven.compiler.targetmaven-compiler-plugin

Bem, se você não precisar especificar outras propriedades ou comportamento além das versões Java no plug-in do compilador, usar dessa maneira faz mais sentido, pois é mais conciso:

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

Do Java 9:

O releaseargumento (terceiro ponto) é uma maneira de considerar fortemente se você deseja usar a mesma versão para a origem e o destino.

O que acontece se a versão diferir entre o JDK em JAVA_HOME e qual especificado no pom.xml?

Não é um problema se o JDK referenciado pelo JAVA_HOMEé compatível com a versão especificada na pom mas para garantir uma melhor compatibilidade cross-compilação pensar sobre a adição da bootstrapopção JVM com o maior valor o caminho do rt.jarda targetversão.

Uma coisa importante a considerar é que a sourceea targetversão na configuração Maven não deve ser superior à versão JDK referenciado pelo JAVA_HOME.
Uma versão mais antiga do JDK não pode ser compilada com uma versão mais recente, pois não conhece sua especificação.

Para obter informações sobre a origem, o destino e a versão suportada, de acordo com o JDK usado, consulte a compilação java: fonte, o destino e a versão suportada .


Como lidar com o caso do JDK referido pelo JAVA_HOME não é compatível com o destino java e / ou as versões de origem especificadas no pom?

Por exemplo, se você se JAVA_HOMEreferir a um JDK 1.7 e especificar um JDK 1.8 como origem e destino na configuração do compilador do seu pom.xml, será um problema porque, conforme explicado, o JDK 1.7 não sabe como compilar com .
Do seu ponto de vista, é uma versão desconhecida do JDK desde que foi lançada depois dela.
Nesse caso, você deve configurar o plug-in do compilador Maven para especificar o JDK desta maneira:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerVersion>1.8</compilerVersion>      
        <fork>true</fork>
        <executable>D:\jdk1.8\bin\javac</executable>                
    </configuration>
</plugin>

Você pode obter mais detalhes em exemplos com o plug-in do compilador maven .


Não é solicitado, mas os casos em que isso pode ser mais complicado são quando você especifica a origem, mas não o destino. Pode usar uma versão diferente no destino, de acordo com a versão de origem. As regras são particulares: você pode ler sobre elas na parte Opções de compilação cruzada .


Por que o plug-in do compilador é rastreado na saída na execução do packageobjetivo do Maven, mesmo que você não o especifique no pom.xml?

Para compilar seu código e, de maneira mais geral, executar todas as tarefas necessárias para um objetivo final, o Maven precisa de ferramentas. Portanto, ele usa plugins principais do Maven (você reconhece um plug-in principal do Maven por groupId: org.apache.maven.plugins:) para executar as tarefas necessárias: plug-in do compilador para compilar classes, plug-in de teste para executar testes e assim por diante ... Então, mesmo que você não o faça declarar esses plug-ins, eles estão vinculados à execução do ciclo de vida do Maven.
No diretório raiz do seu projeto Maven, você pode executar o comando: mvn help:effective-pompara obter o pom final efetivamente usado. Você pode ver, entre outras informações, plugins anexados pelo Maven (especificados ou não no seu pom.xml), com a versão usada, sua configuração e os objetivos executados para cada fase do ciclo de vida.

Na saída do mvn help:effective-pomcomando, você pode ver a declaração desses plugins principais no <build><plugins>elemento, por exemplo:

...
<plugin>
   <artifactId>maven-clean-plugin</artifactId>
   <version>2.5</version>
   <executions>
     <execution>
       <id>default-clean</id>
       <phase>clean</phase>
       <goals>
         <goal>clean</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
 <plugin>
   <artifactId>maven-resources-plugin</artifactId>
   <version>2.6</version>
   <executions>
     <execution>
       <id>default-testResources</id>
       <phase>process-test-resources</phase>
       <goals>
         <goal>testResources</goal>
       </goals>
     </execution>
     <execution>
       <id>default-resources</id>
       <phase>process-resources</phase>
       <goals>
         <goal>resources</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
 <plugin>
   <artifactId>maven-compiler-plugin</artifactId>
   <version>3.1</version>
   <executions>
     <execution>
       <id>default-compile</id>
       <phase>compile</phase>
       <goals>
         <goal>compile</goal>
       </goals>
     </execution>
     <execution>
       <id>default-testCompile</id>
       <phase>test-compile</phase>
       <goals>
         <goal>testCompile</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
  ...

Você pode obter mais informações sobre isso na introdução do ciclo de vida do Maven na documentação do Maven .

No entanto, você pode declarar esses plug-ins quando desejar configurá-los com outros valores como valores padrão (por exemplo, você o fez quando declarou o plug-in maven-compiler em seu pom.xml para ajustar a versão do JDK a ser usada) ou quando deseja adicionar algumas execuções de plug-ins não usadas por padrão no ciclo de vida do Maven.

davidxxx
fonte
Obrigado pela extensa explicação, agora é muito mais claro para mim. Também sobre o <java.version> - eu já vi isso em algum trecho de código, talvez isso fosse alguma propriedade personalizada e eu assumi erroneamente que é a maneira de declarar a versão java, que permanecerá na <maven.compiler.x>propriedade a partir de agora.
Plebejusz
Seja bem-vindo, com prazer :) Inicialmente, não era minha intenção desenvolver muito, mas quando comecei, não consegui parar :) Para `<java.version>`, é muito provável. Vejo você e bom maven!
Davidxxx
1
" não é um problema se o JDK do seu JAVA_HOME é compatível com as versões especificadas no pom " isso não é (necessariamente) verdadeiro, verifique este encadeamento do Stack Overflow para referência
A_Di-Matteo 01/09/16
2
@ Robin A. Meade, obrigado pelo feedback. Eu uso bota de primavera, mas eu não sabia disso. Pessoalmente, não achei padrão o suficiente para ser usado ou referenciado como algo a ser usado. A bota Spring oferece algumas coisas muito interessantes, mas em alguns casos seus recursos são muito discutíveis. Substituir o nome de uma propriedade maven padrão para não preencher a fonte e o destino jdk parece realmente uma péssima idéia, pois é realizada uma única vez para um aplicativo. Você perde o padrão para poupar uma linha xml simples em seu aplicativo. Woah! Que idéia ...
davidxxx 12/01
1
@ MasterJoe2 Você o encontra na documentação oficial do javac da versão 10: docs.oracle.com/javase/10/tools/javac.htm#JSWOR627 . Eu dividi essa resposta em duas partes, pois ela ficou muito grande; você também pode ver isso: stackoverflow.com/questions/51692748/…
davidxxx
3

Nenhuma das soluções acima funcionou para mim imediatamente. Então eu fiz o seguinte: -

  1. Adicionado

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

    em pom.xml

  2. Fui até o Project Properties > Java Build Path, e então removi a Biblioteca do Sistema JRE para a qual estava apontando JRE1.5.

  3. Force atualizou o projeto.

Sen
fonte
Qual versão você especifica para Java 10 e superior? São 10 ou 1,10?
MasterJoe2 9/03
@ MasterJoe2 das versões java 9 e posteriores, você precisa escrever o número da versão como está (<versão 10) e nas versões abaixo, você deve adicionar 1. na frente da versão (versão) 1.5 </version>)
ikbel benab em 8/06
0

Considere a alternativa:

<properties>
    <javac.src.version>1.8</javac.src.version>
    <javac.target.version>1.8</javac.target.version>
</properties>

Deve ser a mesma coisa, maven.compiler.source/maven.compiler.targetmas a solução acima funciona para mim, caso contrário, a segunda recebe a especificação pai (eu tenho uma matrioska de .pom)

Stefano
fonte