SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Java 9で「変わること」と、Javaのこれまで

作成したライブラリの公開と実行イメージの作成

Java 9で「変わること」と、Javaのこれまで 第7回


  • X ポスト
  • このエントリーをはてなブックマークに追加

 本連載では主に開発フェーズにフォーカスしJava 9の変更点を紹介してきましたが、最終回である今回は、開発後のリリースを中心に変更点を紹介します。また、すでにJava 10がリリースされましたが言語仕様にかかわる変更点はあまりありません。特に言語仕様やAPIの変更においてはJava 9が大きな分岐点であり、Java 10以降を理解する上でもJava 9での変更点を理解することは非常に大切なことと言えます。ただし、JDKのサポートに関して注意すべきことがあります。Oracle JDK 9はJDK 10のリリースと共にサポート期限を迎えてしまったため、Oracle JDKを利用する場合には、今後はJDK 10を利用する必要があります。JDKの位置づけはこれまでのJava 8以前と異なっていく予定であり、これらに関しては今後の連載であるJava 10の記事内で紹介します。

  • X ポスト
  • このエントリーをはてなブックマークに追加

Java 9以降とそれ以前のプログラムをサポートするライブラリを作成する

 これまでに紹介したとおり、Java 9での大きな変更点はモジュール機能です。この違いにより、Java 9以降のモジュール対応したコードはそれ以前の環境では動きません。こういった大きな分断は、これまでのJavaにおける変更にはありませんでした。

 そのため、Java 9以降への最適化か、それ以前で動くことを前提にした対応か、といった2つの選択肢になります。ただし、ライブラリ作成者がこのいずれか一方のみを選ばざるを得ない場合、これまでの環境優位性が大きく落ちてしまいます。

 そこで、Java 9からバージョンでの問題を回避するために、複数のバージョンに対応したクラスファイルやリソースファイルを1つのjarファイルに格納することができる「Multi-Release Jar Files」という機能が加わりました。

 その考え方は非常に単純であり、単にJava 9以前をサポートするjarファイルの中にJava 9以降向けのクラスファイルやリソースファイルも含めて1つのjarファイルとして配布するといったものです。また、この機能はモジュール機能のためだけにあるわけではなく、モジュール機能を使っていなくても利用できます。

Multi-Release Jar Filesの構造

 Multi-Release Jar Filesの構造をもったjarファイルを作るには、大きく分けて2つのルールを守る必要があります。

 1つめは、Javaファイルに含めるマニフェストファイル内の記述ルールです。そして、もう1つは、jarファイル内のフォルダ構造です。

 マニフェストファイルには、リスト1に示すとおり、Multi-Releaseの指定が必要です。

リスト1 Multi-Releaseに対応したjarファイルを指定するためのMANIFEST.MFファイル
Manifest-Version: 1.0
Multi-Release: true // この指定を追加する

 また、jarファイル内のフォルダ構造は図1のようにする必要があります。

図1 Multi-Release Jar Filesのフォルダ構造
図1 Multi-Release Jar Filesのフォルダ構造

 図1内で、versions/9以外にversions/10も記述したのは、この構造はJava 9以上のバージョンに対しても利用可能であることを示すためです。ただし、利用できるバージョン指定はメジャーバージョンのみであるため、9.1や、10.3といった記述はできません。

Multi-Release Jar Filesの作成方法

 Multi-Release Jar Filesに沿ったjarファイルを作るには、Java 9以前の既存のコードと、Java 9向けのコードを用意する必要があります。

 サンプルでは同じクラスをもつJava 8(mrlib8)とJava 9(mrlib9)向けのコードを、図2に示す構造にて2つ用意しました。

図2 サンプルコードのフォルダ・ファイル構造
図2 サンプルコードのフォルダ・ファイル構造

 これら2つのプロジェクトでは同じクラス名を使っていますが、実装はそれぞれ異なっています。例えば、Java 8用に自分自身のプロセスIDを取得するコードを実装したものがリスト2です。

リスト2 Java 8用の自分のプロセスIDを取得するためのコード(mrlib8/src/main/java/com/coltware/mrlib/Process.java)
import java.lang.management.ManagementFactory;

public class Process {
    public static long getPid(){
        String name = ManagementFactory.getRuntimeMXBean().getName();
        int idx = name.indexOf('@');
        if(idx < 0){
            return 0L;
        }
        return Long.parseLong(name.substring(0,idx));
    }
}

 Java 9ではプロセスAPIが新たに追加されているため、JMXを使った実装は必要ありません。

 そこで、Java 9用に記述し直したコードがリスト3です。

リスト3 Java 9用の自分のプロセスIDを取得するためのコード(mrlib9/src/main/java/com/coltware/mrlib/Process.java)
public class Process {
    public static long getPid(){
        ProcessHandle handle = ProcessHandle.current();
        return handle.pid();
    }
}

 このように同じクラス、メソッドとして異なる実装を提供することができます。

 そして、これらのコードからjarファイルを作成する手順がリスト4です。

リスト4 jarファイルを作成する手順(mrlib/build.sh)
## Java 8用のjarファイルを作成
javac --release 8 -d mrlib8/classes $(find mrlib8/src/main/java -name "*.java")  (1)Java 8用にコンパイル
jar -cfe mrjar.jar com.coltware.Main -C mrlib8/classes .                         (2)Java 8用のjarファイルの作成

## Java 9向けに変更
javac --release 9 -d mrlib9/classes $(find mrlib9/src/main/java -name "*.java")  (3)Java 9用にコンパイル
jar -uf  mrjar.jar --release 9 -C mrlib9/classes .   (4)Java 9用のクラスファイルをjarファイルに追加

 (1)では、Java 8向けにコンパイルをしています。javaコマンドに新たに追加された--releaseオプションを使っていますが、こちらは、今までの-sourceと-targetを同時に指定することとほぼ同様のオプションです。次に(2)では、作成されたclassファイルを使ってjarファイルを作成します。もし、すでにJava 8等で作成されたjarファイルがあればそれを使っても問題ありません。

 そして、(3)ではJava 9向けにコンパイルします。このときにはもちろん、JDK 9を使います。また、ここまでは、Multi-Release向けの作業ではありませんので、実際のプロジェクトではそのプロジェクトに応じたコンパイルのオプションやjarファイルの作成はそれらのプロジェクトに応じて変更してください。

 そして、(4)のjarコマンドで新たに用意された"--release"オプションに"9"を指定し、Java 9向けのコードをjarファイル内にパッケージングします。

 この行程で自動的にMANIFEST.MFファイル内には、Multi-Release指定が追加されますので、Java 9向けにMANIFEST.MFファイルを自分で用意したり編集したりする必要はありません。

 こうして作られたjarファイルのファイルエントリがリスト5です。

リスト5 作成されたjarファイルの中身
     0 META-INF/
   113 META-INF/MANIFEST.MF
     0 com/
     0 com/coltware/
     0 com/coltware/mrlib/
   698 com/coltware/mrlib/Process.class
   311 com/coltware/mrlib/Hello.class
   826 com/coltware/Main.class
     0 META-INF/versions/9/
     0 META-INF/versions/9/com/
     0 META-INF/versions/9/com/coltware/
     0 META-INF/versions/9/com/coltware/mrlib/
   370 META-INF/versions/9/com/coltware/mrlib/Process.class
   311 META-INF/versions/9/com/coltware/mrlib/Hello.class
  1063 META-INF/versions/9/com/coltware/Main.class
   238 META-INF/versions/9/module-info.class

 また、今回jarコマンドにて作成しましたが、自分でjavaコマンドやjarコマンドを使って作業をするのではなく、IDEやMavenもしくはGradleなどを使って作業をしているというケースも多いと思います。

 それらのツールは今回のMulti-Release Jar Filesの機能に対応していないことがありますが、その場合にはjarファイル内のフォルダ構造とマニフェストファイルのルールに準拠した形でjarファイルを作成すれば問題ありません。

 例えば、Gradleであればリスト6のとおり作成することが可能です。

リスト6 作成されたjarファイルの中身
jar {
    from new File("mrlib8/classes")      //  Java 8のclassファイルの場所を指定

    into('META-INF/versions/9') {
        from new File("mrlib9/classes")  //  Java 9のclassコードの場所を指定
    }
    manifest.attributes(
            'Multi-Release': 'true'      //  Multi-Release: trueの指定追加
    )
}

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
アプリケーションの実行時イメージを作成する

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Java 9で「変わること」と、Javaのこれまで連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/10764 2018/04/19 11:31

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング