2010-09-03 26 views
14

Tôi có dự án này được làm từ nhiều lọ và chiến tranh để tạo tai. Tôi xây dựng mọi thứ trong ảnh chụp nhanh và nó hoạt động rất tốt. Sau đó, tôi đã thực hiện một bản phát hành cho mỗi dự án duy nhất và thấy rằng các lọ và chiến tranh có kích thước hơi khác so với các ảnh chụp nhanh.Plugin phát hành Maven: chỉ định phiên bản trình biên dịch java

So sánh tệp với tệp Tôi nhận ra rằng các tệp .class đều ở đó, nhưng lớn hơn một chút hoặc lớn hơn, không có gì lớn hơn 40 byte nói chung.

tôi buộc biên soạn để sử dụng java 1,5 sử dụng thẻ này trong 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> 

tôi sử dụng thẻ này cho các plugin phát hành:

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

Nó có thể được rằng các plugin phát hành được biên soạn trong 1,6 hoặc khác, giải thích sự khác biệt kích thước lớp học? Nếu vậy tôi có thể làm cho các plugin phát hành biên dịch trong 1,5?

Cảm ơn bạn đã nhập.

+0

Nếu bạn thử chạy các bình đã giải phóng ở 1,5, chúng có chạy trong 1,5 không? Hoặc bạn có nhận được một jar không hợp lệ/bị lỗi ngoại lệ, nói với bạn rằng họ có thể biên dịch trên một phiên bản sau? – aperkins

+0

Cả hai hình chụp và bình nhả có vẻ hoạt động, chạy ở chế độ 1.5. Tôi chưa gặp lỗi, nhưng tôi không hiểu điều gì làm cho các lớp có kích thước khác nhau. Tôi chỉ hy vọng một cái gì đó sẽ không nhảy vào tôi khi điều này đạt đến sản xuất. – IceGras

+0

@IceGras, nó có thể nguy hiểm, tôi giải thích tại sao trong câu trả lời của tôi dưới đây ... Tóm lại, _references cho các phương thức không tồn tại có thể nhận được include_ – Lucas

Trả lời

1

Bạn có thể xác minh phiên bản một lớp được biên dịch bằng cách sử dụng tiện ích javap đi kèm với JDK. Từ dòng lệnh:

javap -verbose MyClass 

Trong đầu ra của javap tìm "phiên bản nhỏ" và "phiên bản chính" khoảng mười dòng xuống.

Sau đó sử dụng bảng này:

 
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 

Các .class chênh lệch kích thước có thể là do biên dịch phiên bản nhưng cũng có thể là do tùy chọn biên dịch khác như biên dịch với các thông tin gỡ lỗi (số dòng trong stacktraces).

+0

Trên macOS (10.12.6 ít nhất), đầu ra từ tệp ** * lệnh thậm chí còn hữu ích hơn, ví dụ 'tệp MyClass.class' có thể tạo ra:' MyClass.class: dữ liệu lớp Java đã biên dịch, phiên bản 50.0 (Java 1.6) ' – Gary

0

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

Không thể là IMO. Maven Release Plugin không biên dịch bất cứ thứ gì, nó chỉ kích hoạt một pha sẽ tự kích hoạt pha compile và Trình biên dịch Maven. Nói cách khác, Maven Compiler Plugin và các thiết lập của nó sẽ được sử dụng.

Bạn có thể sử dụng các lệnh sau để kiểm soát những gì đang xảy ra chính xác:

mvn help:active-profiles -Prelease 

để kiểm tra hồ sơ. Và

mvn help:effective-pom -Prelease 

để kiểm tra hiệu quả của pom.

+0

Tôi có cùng một vấn đề. Tôi có '' và '' được chỉ định trong tệp pom của tôi là 1,6. Khi tôi chạy 'mvn package', tôi sẽ thành công. Tuy nhiên, khi tôi chạy 'mvn release: prepare' nó không thành công với lỗi' TunneledDataSourceWrapper.java:[17,7]: TunneledDataSourceWrapper không trừu tượng và không ghi đè phương thức trừu tượng getParentLogger() trong CommonDataSource', đó là dấu hiệu cho thấy nó đang cố gắng để biên dịch java 7 _ (java 7 đã thêm một phương thức vào CommonDataSource làm cho nó không tương thích với 6) _. – Lucas

18

--- SPOILER ALERT ---

Câu trả lời ngắn gọn là để biên dịch mã nguồn cho một phiên bản cũ hơn, bạn cần phải cung cấp cả tùy chọn -source cũng như -bootclasspath. Xem this article. Và nếu bạn muốn biên dịch mã nguồn sang một phiên bản mới hơn, bạn cần phải thiết lập <source>, <target>, <compilerVersion>, <fork><executable> trên các plugin trình biên dịch, thiết <jvm> trên plugin chắc chắn hơn ...

Và bây giờ cho câu chuyện ...

Tôi đã gặp phải sự cố tương tự. Hóa ra việc biên soạn phiên bản trước có thể không dễ dàng như cài đặt <source><target>. Trường hợp cụ thể của tôi là tôi có Java 1.7 JDK và lớp của tôi có tính không tương thích với 1.7 (họ đã thêm phương thức mới vào giao diện mà tôi đang triển khai). Khi tôi cố gắng biên dịch nó, trình biên dịch đã cho tôi một thông báo lỗi nói rằng tôi đã không thực hiện phương thức giao diện. Dù sao, tôi đã thử cài đặt plugin trình biên dịch:

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

nhưng khi tôi chạy bản dựng, tôi gặp lỗi tương tự. Vì vậy, tôi chạy maven trong gỡ lỗi và thấy điều này:

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

Lưu ý rằng ... được đặt ở vị trí của đối số thực tế vì lợi ích của ngắn gọn

trong đầu ra. Thông báo bắt đầu bằng -d là danh sách đối số biên dịch đầy đủ thực tế. Vì vậy, nếu bạn loại bỏ các -nowarn cờ và dán phần còn lại sau khi javac trên dòng lệnh bạn sẽ nhìn thấy đầu ra thực tế từ trình biên dịch:

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 

này in ra cảnh báo đường dẫn lớp bootstrap tiện dụng-dandy không được thiết lập trong kết hợp với nguồn 1.6. Một chút googling trên đó lần lượt lên this article trong đó nêu:

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.

Bây giờ tham khảo the maven documentation for the compiler plugin cho:

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

nào thì bạn có thể kết hợp với cấu hình trước đó của bạn để nhận được:

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

Và bây giờ bạn chỉ cần tạo biến số ${java.home} cho mvn của bạn (thông qua các thuộc tính hệ thống -D, hoặc thông qua đồng bằng biến môi trường cũ, hoặc bạn có thể nhận được thực sự ưa thích và thứ nó trong một cấu hình java 6 trong cài đặt người dùng của bạn).

Bây giờ chỉ cần chạy build của bạn và đi lấy một ly bia lạnh trong khi nó chugs đi ...

---- EDIT ----

Một điều cuối cùng ... Bao gồm rt.jar trong tuy nhiên, đường dẫn khởi động của bạn là luôn luôn là, tuy nhiên, tôi phát hiện ra rằng có thể cần nhiều hơn trong từng trường hợp. Tôi đã bao gồm jce.jar (trong cùng thư mục với rt.jar) vì ứng dụng của tôi đang thực hiện công việc mã hóa.

---- CHỈNH SỬA 2 ----

Đối với nụ cười, tôi đã thử theo hướng khác. Thay vì chạy maven với java 7 biên soạn cho java 6, tôi chạy maven với java 6 biên soạn cho java 7. Các nỗ lực đầu tiên là khá thẳng về phía trước:

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

Về cơ bản, tôi đặt <source> tôi và <target>-1,7, nhưng rõ ràng là không đủ vì 6 không thể biên dịch 7 mã. Vì vậy, trở lại plugin trình biên dịch, có thực sự là an example page mô tả những gì cần phải được thực hiện.Cụ thể, bạn cần phải <fork> tắt một quy trình mới bằng cách sử dụng java 7 <executable>. Vì vậy, bây giờ tôi nghĩ rằng tôi là tất cả các thiết lập. Đã đến lúc đốt cháy tòa nhà ...

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

Heck là gì UnsupportedClassVersionError? Một cái nhìn gần hơn cho chúng ta biết plugin maven-surefire của nó đang thất bại. Vì vậy, tôi thử chỉ mvn compile và chắc chắn đủ tôi nhận được một thành công như plugin chắc chắn không bao giờ bắn lên. Vì vậy, tôi chạy mvn -X package và thông báo đá quý này:

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, do đó, chạy java 6. Tại sao? Tài liệu cho chắc chắn cung cấp cho điều này:

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. 

Vì chúng tôi chạy mvn với java 6 VM, hãy thử một máy ảo Java 6 cho các bài kiểm tra đơn vị của nó. Vì vậy, thiết lập tùy chọn này một cách thích hợp:

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

Và bắn lên xây dựng ...

[INFO] ------------------------------------------------------------------------ 
[INFO] BUILD SUCCESS 
[INFO] ------------------------------------------------------------------------ 
+0

Có điều gì đã thay đổi với Java 8 không? Tôi đang xây dựng với một mục tiêu của Java 6 và nếu tôi đặt 'bootclasspath' trong tệp' pom.xml' của mình, tôi nhận được tệp lớp 'đáng sợ có sai phiên bản 52.0, phải là 50.0'. Khi tôi xóa * 'compilerArguments' và chỉ giữ' source' và 'target', bản build của tôi không bị lỗi. Đó hoàn toàn trái ngược với câu trả lời này. Thêm chi tiết trong câu hỏi này: http://stackoverflow.com/questions/34854961/class-file-has-wrong-version-after-jenkins-upgrade –

+0

@AmedeeVanGasse, xin lỗi, tôi không biết gì về điều gì sẽ gây ra Java 8 hành xử khác với tình huống trên. – Lucas

+0

Không sao cả. Tôi nghi ngờ một phiên bản rất cũ của trình biên dịch Maven plugin, bởi vì nó hoạt động chính xác như trong ví dụ của bạn với phiên bản hiện tại, 3.3, và các tham số chính xác như trong câu trả lời của bạn. Đặc biệt nhất, nhưng đó là sự tinh tế của Maven. –

0

Chỉ cần một lưu ý, nếu một phiên bản sai được nhặt, bạn sẽ nhận được một cái gì đó lỗi như

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

Trong khi phát hành maven, plugin phát hành maven (bộ/mặc định thành) phiên bản trình biên dịch 1.5. Để đảm bảo nó chọn lên phiên bản chính xác xác định các thuộc tính.

<properties> 
<maven.compiler.source>1.7</maven.compiler.source> 
<maven.compiler.target>1.7</maven.compiler.target> 
</properties> 
Các vấn đề liên quan