java-multi-release-jar
マルチリリースjarファイル
1. 概要
Javaは常に進化し、JDKに新しい機能を追加しています。 また、APIでこれらの機能を使用する場合、ダウンストリームの依存関係でJDKバージョンをアップグレードする必要があります。
時々、互換性を保つために、新しい言語機能の使用を待つ必要があります*。
ただし、このチュートリアルでは、Multi-Release JAR(MRJAR)について学習し、*異なるJDKバージョンと互換性のある実装を同時に含める方法を学習します。*
2. 簡単な例
link:/java-leap-year[leap years]をチェックするメソッドを持つ_DateHelper_erというユーティリティクラスを見てみましょう。 JDK 7を使用して作成され、JRE 7以降で実行するようにビルドされていると仮定します。
public class DateHelper {
public static boolean checkIfLeapYear(String dateStr) throws Exception {
logger.info("Checking for leap year using Java 1 calendar API ");
Calendar cal = Calendar.getInstance();
cal.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr));
int year = cal.get(Calendar.YEAR);
return (new GregorianCalendar()).isLeapYear(year);
}
}
_checkIfLeapYear_メソッドは、テストアプリの_main_メソッドから呼び出されます。
public class App {
public static void main(String[] args) throws Exception {
String dateToCheck = args[0];
boolean isLeapYear = DateHelper.checkIfLeapYear(dateToCheck);
logger.info("Date given " + dateToCheck + " is leap year: " + isLeapYear);
}
}
今日に早送りしましょう。
Java 8にはもっとlink:/java-8-date-time-intro [日付を解析する簡潔な方法]があることがわかっています。 そこで、これを利用してロジックを書き直したいと思います。 *このためには、JDK 8以降に切り替える必要があります。 ただし、それは、最初に作成されたJRE 7でモジュールが動作しなくなることを意味します。*
そして、絶対に必要な場合を除き、そのようなことは望ましくありません。
3. マルチリリースjarファイル
Java 9の解決策は、*元のクラスをそのままにして、代わりに新しいJDKを使用して新しいバージョンを作成し、それらを一緒にパッケージ化することです*。 実行時に、JVM(バージョン9以降)は、これら2つのバージョンのいずれかを呼び出します* JVMがサポートする最高のバージョンを優先します*。
たとえば、MRJARに同じバージョンのJavaバージョン7(デフォルト)、9および10が含まれている場合、JVM 10はバージョン10を実行し、JVM 9はバージョン9を実行します。 どちらの場合も、そのJVMにより適切なバージョンが存在するため、デフォルトバージョンは実行されません。
クラスの新しいバージョンの*パブリック定義は、元のバージョンと完全に一致する必要があることに注意してください*。 つまり、新しいバージョン専用の新しいパブリックAPIを追加することはできません。
4. フォルダー構造
Javaのクラスは名前によってファイルに直接マッピングされるため、同じ場所に_DateHelper_の新しいバージョンを作成することはできません。 したがって、別のフォルダーに作成する必要があります。
_java_と同じレベルに_java9_フォルダーを作成することから始めましょう。 その後、パッケージフォルダー構造を保持した_DateHelper.java_ファイルを複製して、_java9:_に配置します。
src/
main/
java/
com/
baeldung/
multireleaseapp/
App.java
DateHelper.java
java9/
com/
baeldung/
multireleaseapp/
DateHelper.java
-
MRJAR *をまだサポートしていないIDEには、重複した_DateHelper.java_クラスに対してエラーをスローするものがあります。
別のチュートリアルでhttps://maven.apache.org/plugins/maven-compiler-plugin/multirelease.html [これをMavenなどのビルドツールと統合する方法]を取り上げます。 とりあえず、基本に注目しましょう。
5. コードの変更
_java9_クローンクラスのロジックを書き直しましょう。
public class DateHelper {
public static boolean checkIfLeapYear(String dateStr) throws Exception {
logger.info("Checking for leap year using Java 9 Date Api");
return LocalDate.parse(dateStr).isLeapYear();
}
}
ここで、*クローンクラスのパブリックメソッドシグネチャは変更せず、内部ロジックのみを変更していることに注意してください。 同時に、新しいパブリックメソッドは追加していません。*
これらの2つのルールに従わないとjarの作成が失敗するため、これは非常に重要です。
6. Javaでのクロスコンパイル
クロスコンパイルは、以前のバージョンで実行するためにファイルをコンパイルできるJavaの機能です。 つまり、個別のJDKバージョンをインストールする必要はありません。
JDK 9以降を使用してクラスをコンパイルしましょう。
まず、Java 7プラットフォーム用の古いコードをコンパイルします。
javac --release 7 -d classes src\main\java\com\baeldung\multireleaseapp\*.java
次に、Java 9プラットフォーム用の新しいコードをコンパイルします。
javac --release 9 -d classes-9 src\main\java9\com\baeldung\multireleaseapp\*.java
_release_オプションは、JavaコンパイラとターゲットJREのバージョンを示すために使用されます。
7. MRJARの作成
最後に、バージョン9以降を使用してMRJARファイルを作成します。
jar --create --file target/mrjar.jar --main-class com.baeldung.multireleaseapp.App
-C classes . --release 9 -C classes-9 .
-
_release_オプションの後にフォルダー名を指定すると、そのフォルダーの内容がバージョン番号の値でjarファイル内にパッケージ化されます。*
com/
baeldung/
multireleaseapp/
App.class
DateHelper.class
META-INF/
versions/
9/
com/
baeldung/
multireleaseapp/
DateHelper.class
MANIFEST.MF
_MANIFEST.MF_ファイルには、これがMRJARファイルであることをJVMに知らせるためのプロパティセットがあります。
Multi-Release: true
その結果、JVMは実行時に適切なクラスをロードします。
古いJVMは、これがMRJARファイルであることを示す新しいプロパティを無視し、通常のJARファイルとして扱います。
8. テスト
最後に、Java 7または8に対してjarをテストしましょう。
> java -jar target/mrjar.jar "2012-09-22"
Checking for leap year using Java 1 calendar API
Date given 2012-09-22 is leap year: true
次に、jarをJava 9以降に対して再度テストしましょう。
> java -jar target/mrjar.jar "2012-09-22"
Checking for leap year using Java 9 Date Api
Date given 2012-09-22 is leap year: true
9. 結論
この記事では、簡単な例を使用してマルチリリースjarファイルを作成する方法を説明しました。
いつものように、multi-release-appのコードベースはhttps://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-9[GitHub上]で入手できます。