Chỉ định phiên bản java trong maven - sự khác biệt giữa các thuộc tính và plugin trình biên dịch


178

Tôi không có nhiều kinh nghiệm với maven và trong khi thử nghiệm với dự án đa mô-đun, tôi bắt đầu tự hỏi làm thế nào tôi có thể chỉ định phiên bản java cho tất cả các mô-đun con của tôi trong cha mẹ maven pom. Cho đến hôm nay tôi chỉ sử dụng:

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

nhưng khi nghiên cứu tôi thấy rằng bạn cũng có thể chỉ định phiên bản java trong plugin trình biên dịch maven, như thế:

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

Và sau đó bọc nó vào thẻ quản lý plugin để cho phép sử dụng poms con này. Vì vậy, câu hỏi đầu tiên là sự khác biệt giữa cài đặt phiên bản java trong các thuộc tính và trong trình biên dịch maven là gì?

Tôi không thể tìm thấy câu trả lời rõ ràng nhưng trong quá trình nghiên cứu tôi thấy rằng bạn cũng có thể chỉ định phiên bản java theo cách này:

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

Điều đó cho thấy plugin trình biên dịch có ngay cả khi tôi không khai báo rõ ràng. Chạy đầu ra gói mvn với

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

và một số plugin khác mà tôi đã không khai báo. Vì vậy, các plugin mặc định, một phần ẩn của maven pom? Có sự khác biệt nào khi thiết lập nguồn / đích trong các thuộc tính và trong thành phần cấu hình plugin maven không?

Một số câu hỏi khác là - nên sử dụng cách nào (và khi nào chúng không bằng nhau)? Cái nào là tốt nhất cho dự án đa mô-đun và điều gì xảy ra nếu phiên bản java được chỉ định trong pom khác với phiên bản được chỉ ra trong JAVA_HOME?

Câu trả lời:


288

Làm thế nào để xác định phiên bản JDK?

1) <java.version>không được tham chiếu trong tài liệu Maven.
Đó là một đặc tính của Spring Boot.
Nó cho phép đặt nguồn và phiên bản java đích với cùng một phiên bản như phiên bản này để chỉ định java 1.8 cho cả hai:

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

Hãy sử dụng nó nếu bạn sử dụng Spring Boot.

2) Sử dụng maven-compiler-pluginhoặc maven.compiler.source/ maven.compiler.targetthuộc tính để chỉ định sourcetargettương đương.

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

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

tương đương theo tài liệu Maven của plugin trình biên dịch<source>và các <target>thành phần trong cấu hình trình biên dịch sử dụng các thuộc tính maven.compiler.sourcemaven.compiler.targetnếu chúng được xác định.

nguồn

Đối -sourcesố cho trình biên dịch Java.
Giá trị mặc định là : 1.6.
Tài sản người dùng là : maven.compiler.source.

Mục tiêu

Đối -targetsố cho trình biên dịch Java.
Giá trị mặc định là : 1.6.
Tài sản người dùng là : maven.compiler.target.

Về các giá trị mặc định cho sourcetarget, lưu ý rằng kể từ 3.8.0trình biên dịch maven, các giá trị mặc định đã thay đổi từ 1.5thành1.6 .

3) Trình biên dịch maven-plugin 3.6và các phiên bản mới hơn cung cấp một cách mới:

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

Bạn cũng có thể tuyên bố chỉ:

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

Nhưng tại thời điểm này, nó sẽ không hoạt động như maven-compiler-pluginphiên bản mặc định mà bạn sử dụng không dựa vào phiên bản đủ gần đây.

Đối releasesố Maven truyền tải release: một tùy chọn tiêu chuẩn JVM mới mà chúng ta có thể chuyển từ Java 9:

Biên dịch dựa trên API công khai, được hỗ trợ và ghi lại cho một phiên bản VM cụ thể.

Bằng cách này cung cấp một cách tiêu chuẩn để xác định các phiên bản tương tự cho các source, các targetvà các bootstraptùy chọn JVM.
Lưu ý rằng việc chỉ định bootstraplà một cách thực hành tốt cho các phần tổng hợp chéo và nó sẽ không bị tổn thương nếu bạn không thực hiện các phần tổng hợp chéo.


Cách tốt nhất để chỉ định phiên bản JDK là gì?

Cách đầu tiên ( <java.version>) chỉ được phép nếu bạn sử dụng Spring Boot.

Đối với Java 8 trở xuống:

Về hai cách khác: định giá maven.compiler.source/ maven.compiler.targetthuộc tính hoặc sử dụng maven-compiler-plugin, bạn có thể sử dụng cách này hoặc cách khác. Nó không thay đổi gì trong thực tế vì cuối cùng hai giải pháp dựa trên cùng một thuộc tính và cùng một cơ chế: plugin trình biên dịch lõi maven.

Chà, nếu bạn không cần chỉ định các thuộc tính hoặc hành vi khác so với các phiên bản Java trong plugin trình biên dịch, sử dụng cách này có ý nghĩa hơn vì điều này ngắn gọn hơn:

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

Từ Java 9:

Đối releasesố (điểm thứ ba) là một cách để xem xét mạnh mẽ nếu bạn muốn sử dụng cùng một phiên bản cho nguồn và đích.

Điều gì xảy ra nếu phiên bản khác nhau giữa JDK trong JAVA_HOME và phiên bản nào được chỉ định trong pom.xml?

Nó không phải là một vấn đề nếu JDK tham chiếu bởi JAVA_HOMEtương thích với các phiên bản được quy định trong pom nhưng để đảm bảo một tương thích chéo biên soạn tốt hơn suy nghĩ về việc thêm các bootstraptùy chọn JVM với giá trị là đường dẫn của rt.jarcác targetphiên bản.

Một điều quan trọng cần xem xét là sourcetargetphiên bản trong cấu hình Maven không nên vượt trội so với phiên bản JDK được tham chiếu bởi JAVA_HOME.
Một phiên bản cũ hơn của JDK không thể biên dịch với phiên bản mới hơn vì nó không biết thông số kỹ thuật của nó.

Để có được thông tin về nguồn, nhắm mục tiêu và phát hành các phiên bản được hỗ trợ theo JDK đã sử dụng, vui lòng tham khảo phần biên dịch java: nguồn, đích và phát hành phiên bản được hỗ trợ .


Làm thế nào xử lý trường hợp JDK được tham chiếu bởi JAVA_HOME không tương thích với mục tiêu java và / hoặc phiên bản nguồn được chỉ định trong pom?

Ví dụ: nếu bạn JAVA_HOMEđề cập đến JDK 1.7 và bạn chỉ định JDK 1.8 làm nguồn và đích trong cấu hình trình biên dịch của pom.xml của bạn, thì đó sẽ là một vấn đề vì như đã giải thích, JDK 1.7 không biết cách biên dịch với .
Từ quan điểm của nó, nó là một phiên bản JDK không xác định kể từ khi nó được phát hành sau nó.
Trong trường hợp này, bạn nên cấu hình plugin trình biên dịch Maven để chỉ định JDK theo cách này:

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

Bạn có thể có nhiều chi tiết hơn trong các ví dụ với plugin trình biên dịch maven .


Nó không được hỏi nhưng trường hợp có thể phức tạp hơn là khi bạn chỉ định nguồn nhưng không nhắm mục tiêu. Nó có thể sử dụng một phiên bản khác trong mục tiêu theo phiên bản nguồn. Các quy tắc rất cụ thể: bạn có thể đọc về chúng trong phần Tùy chọn biên dịch chéo .


Tại sao plugin trình biên dịch được theo dõi trong đầu ra khi thực hiện packagemục tiêu Maven ngay cả khi bạn không chỉ định nó trong pom.xml?

Để biên dịch mã của bạn và nói chung để thực hiện tất cả các nhiệm vụ cần thiết cho mục tiêu maven, Maven cần các công cụ. Vì vậy, nó sử dụng plugin Maven lõi (bạn nhận ra một lõi Maven plugin bằng của nó groupId: org.apache.maven.plugins) để thực hiện các nhiệm vụ yêu cầu: trình biên dịch plugin cho các lớp học biên dịch, kiểm tra plugin cho thực hiện các bài kiểm tra, và như vậy cho ... Vì vậy, ngay cả khi bạn không khai báo các plugin này, chúng bị ràng buộc với việc thực hiện vòng đời Maven.
Tại thư mục gốc của dự án Maven của bạn, bạn có thể chạy lệnh: mvn help:effective-pomđể sử dụng hiệu quả pom cuối cùng. Bạn có thể thấy trong số các thông tin khác, các plugin được đính kèm bởi Maven (được chỉ định hoặc không có trong pom.xml của bạn), với phiên bản được sử dụng, cấu hình của chúng và các mục tiêu được thực hiện cho từng giai đoạn của vòng đời.

Trong đầu ra của mvn help:effective-pomlệnh, bạn có thể thấy phần khai báo của các plugin lõi này trong <build><plugins>phần tử, ví dụ:

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

Bạn có thể có thêm thông tin về nó trong phần giới thiệu về vòng đời Maven trong tài liệu Maven .

Tuy nhiên, bạn có thể khai báo các plugin này khi bạn muốn định cấu hình chúng với các giá trị khác làm giá trị mặc định (ví dụ: bạn đã làm điều đó khi bạn khai báo plugin trình biên dịch maven trong pom.xml để điều chỉnh phiên bản JDK để sử dụng) hoặc khi bạn muốn thêm một số thực thi plugin không được sử dụng theo mặc định trong vòng đời Maven.


Cảm ơn đã giải thích sâu rộng, bây giờ nó rõ ràng hơn nhiều đối với tôi. Ngoài ra về <java.version> - Tôi đã thấy điều này trong một số đoạn mã, có thể đó là một số thuộc tính tùy chỉnh và tôi đã sai khi cho rằng đó là cách khai báo phiên bản java, <maven.compiler.x>từ bây giờ sẽ dính vào thuộc tính.
Plebejusz

Bạn được chào đón, với niềm vui :) Ban đầu, tôi không có ý định phát triển quá nhiều nhưng khi tôi bắt đầu, tôi không thể dừng lại :) Đối với `<java.version>` rất có khả năng. Hẹn gặp lại và maven tốt!
davidxxx

1
" Nó không phải là một vấn đề nếu JDK của JAVA_HOME của bạn là tương thích với các phiên bản được quy định trong pom " này không (necessarely) đúng, kiểm tra này chủ đề Stack Overflow để tham khảo
A_Di-Matteo

2
@Robin A. Meade cảm ơn bạn đã phản hồi. Tôi sử dụng boot mùa xuân nhưng tôi không biết điều đó. Cá nhân tôi không thấy nó đủ tiêu chuẩn để được sử dụng hoặc được tham chiếu như một cái gì đó để sử dụng. Spring boot cung cấp một số điều rất thú vị nhưng trong một số trường hợp, các tính năng của nó rất đáng tin cậy. Ghi đè tên của thuộc tính maven tiêu chuẩn để không điền cả nguồn và jdk đích thực sự là một ý tưởng tồi vì nó được thực hiện một lần duy nhất cho một ứng dụng. Bạn mất tiêu chuẩn để dự phòng một dòng xml đơn giản trong ứng dụng của bạn. Ái chà! Thật là một ý tưởng ...
davidxxx

1
@ MasterJoe2 Bạn tìm thấy nó trong tài liệu javac chính thức của phiên bản 10: docs.oracle.com/javase/10/tools/javac.htmlm#JSWOR627 . Tôi đã chia câu trả lời đó thành hai phần vì nó trở nên quá lớn, bạn cũng có thể nhìn vào đó: stackoverflow.com/questions/51692748/ hiệu
davidxxx

3

Không có giải pháp nào ở trên làm việc cho tôi ngay lập tức. Vì vậy, tôi đã làm như sau: -

  1. Thêm

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

    trong pom.xml

  2. Đi đến Project Properties > Java Build Path, sau đó xóa Thư viện hệ thống JRE đang trỏ đến JRE1.5.

  3. Lực lượng cập nhật dự án.


Phiên bản nào bạn chỉ định cho Java 10 trở lên? Là 10 hay 1.10?
MasterJoe2

@ MasterJoe2 từ phiên bản java 9 trở lên, bạn cần viết số phiên bản như (<phiên bản> 10 </ phiên bản>) và đối với các phiên bản bên dưới, bạn phải thêm 1. trước phiên bản (<phiên bản> 1.5 </ phiên bản>)
ikbel benab

0

Hãy xem xét lựa chọn thay thế:

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

Nó sẽ là điều tương tự maven.compiler.source/maven.compiler.targetnhưng giải pháp trên hoạt động với tôi, nếu không thì giải pháp thứ hai có được đặc tả cha mẹ (tôi có một matrioska của .pom)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.