--- 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>
và <executable>
trên các plugin trình biên dịch, và 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>
và <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] ------------------------------------------------------------------------
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
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
@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