次のようにいくつかの選択肢があるかと思います。
新しいリリースモデルに併せて、半年ごとにアップデートを実施
通常は、LTS 版を利用しインシデントが発生した時点で対応を検討
サービスに影響のない範囲で自己責任において長期利用
①新しいリリースモデルに併せて、半年ごとのアップデートを実施
半年ごとのアップデートを行っていくためには、事前に次のような内容を準備しておくことでリスクを下げることができるでしょう。
●OpenJDKの動向ウォッチ
正式リリースのスケジュールの把握
アーリー・アクセスビルドの入手とテスト
新機能の確認、削除パッケージの有無などの確認
●テストコードの整備
●継続的インテグレーション(ビルドテスト)
まず、第一にOpenJDKの動向を常にチェックしましょう。最も大事なのは、OpenJDKのサイトで公開される正式リリースの日程を把握することです。この日程を把握することで、自身のアプリケーションの更新スケジュールを立てられるようになります。
次に、アーリーアクセス版のバイナリを入手し事前に検証をしましょう。仮に正式リリースまで検証を待つと、その時点で新たな課題を発見する可能性があります。これにより急な想定外の対応をしなければならず、結果として予定していたよりも導入までに時間を要する可能性があります。アーリーアクセス版で検証しておくことで、こうした課題を早く発見できるでしょう。
また、アーリーアクセス版を試していただくのと同様に、JDK Enhancement Proposal(JEP)を確認しておくこともとても重要です。これにより、新機能追加や変更に対する情報をいち早く入手でき、必要な変更箇所などをあらかじめ把握することが可能になります。
たとえば、Java SE 11より一部のパッケージ(JAX-WS、JAXB、CORBAなど)が削除されましたが、このような場合も、実装しているアプリケーション内で使用しているか、もしくは利用しているサードパーティ製のライブラリで利用されていないかを確認し、それに応じて事前に対応を施すこともできます。
これ以外にも、新機能の追加、さらにはJava VMやGCに対する変更もJEPで定義・記載されていますので、とても重要なドキュメントになります。
アップグレード戦略も次のの2つの方法があります。
ソースコード未修正でアップデート
新しい言語仕様に沿ったソースコードの修正
1:ソースコード未修正でアップデート
1つ目の方法は、既存のソースコードには修正を加えず、Javaの実行環境だけをアップデートする方法です。この方法は今までもありましたが、ソースコードをコンパイルする際に、-source、-target、-bootclasspath オプションを指定してコンパイルします。これにより、-sourceで指定ソースコードを-targetで指定した環境下で動かすことができました。
Java SE 9からはこれらのオプションをまとめた新しい--releaseオプションが追加されています。これを利用することで、指定した環境用のクラスコードを出力してくれます。たとえば、下記の例のようにOpenJDK 11の環境で、Java SE 7のコードを「javac --release 7 Test.java」としてコンパイルが可能です。
この場合Java SE 7用のクラスファイルが生成され、さらにJava VM 11の環境でコードを動かすことができます。ソースコード未修正で環境をアップデートしたい場合は、今後--releaseオプションをご使用ください。
Java SE 7のソースコード例(Test.java)
public class Test{
public static void main(String... args){
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int number : numbers) {
System.out.println("number = " + number);
}
}
}
OpenJDK 11がインストールされている環境で下記を実行します。
$ javac --release 7 Test.java
$ java -version
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
$ java Test
number = 1
number = 2
number = 3
number = 4
number = 5
number = 6
number = 7
number = 8
number = 9
number = 10
新しい言語仕様に沿ったソースコードの修正
新しい言語仕様に沿ったソースコードを修正するためには、上述したように、アーリーアクセス版による検証や、JEPのチェックなどが必要なのはもとより、柔軟なバージョンアップを行うためのビルドテスト環境の充実が必要になります。
JUnitや Seleniumなどによるテストコードの整備、さらにはソースコードのコミット時に自動ビルドや自動テストを行い、素早く変更に対する検証ができるような整備が必要になるでしょう。また素早く検証するために、必要に応じてコンテナ化なども見据えた対応も必要になってくるかと思います。
通常は、LTS版を利用しインシデントが発生した時点で対応を検討
また、従来型のシステム開発や運用、さらにはミッションクリティカル領域での運用においては開発期間も長く、頻繁なJavaのバージョンアップが難しい場合もあるでしょう。その場合はLTS版をご利用いただくことで不測の事態に対応することも可能になります。
通常は、LTS版を利用し開発・運用を行い、Java VMに対する不具合などが発生した場合ベンダ(Oracle、Red Hat、Azul Systemsなど)からのサポートを受ける選択肢を残しておくことで、より長くJavaアプリケーションを安心して本番環境で利用することができるようになります。サポート期間は各ベンダによって異なりますので、どの環境でJavaを動作させるのか、もしくはどのベンダのサポートを受けるのか選択肢の幅は広がっています。
サービスに影響のない範囲で自己責任において長期利用
また、システムを塩漬けにしたいニーズもあるかと思います。外部に公開されているシステムならば、塩漬けをお勧めしませんが、仮に社内ネットワークなど閉じた環境で、かつ信頼されるネットワーク環境下で運用される場合、古いJavaのバージョンのまま運用していただくことも可能かと想定します。この場合は、自己責任の範囲内で長期利用をご検討ください。
Oracle JDKとOpenJDKの違いについて
ここまで、サポートやバージョンアップ、システムへの適用についてまとめてきましたが、最後にOracle JDKとOpenJDKの違いについても触れます。
まず過去の経緯について紹介します。Java SEが初めてオープンソース化されたころ(OpenJDK 6)は、大きな差がありました。しかし、Java SE 8の開発では、Oracle JDKもOpenJDKをベースに開発がされるようになりましたので、以前に比べ差はほとんどありません。
そして、OpenJDKバイナリ の入手方法に関しても、本家 OpenJDKのサイトの他、Azul Systems社が提供するZulu、Javaコミュニティが主導するAdoptOpenJDKなどから入手可能です。その他、Eclipse OpenJ9など、さまざまな選択肢があります。またサポートに関しても Oracle 社によるOracle JDKはもちろん、他社からも各OpenJDKビルドに応じてサポートを受けることができるようになっています。
今では、Javaを無償で使う選択肢も、商用サポートを購入して利用する選択肢も以前より増えています。今後はユーザ自身がさまざまな情報を収集し、どのJava製品が自分の環境に最適かを考えて選択しなくてはならないでしょう。
OpenJDK 12について
2019年は、Java 12、13の2つのバージョンのリリースが予定されています。とくに直近のJava 12については、正式リリース日(米国時間2019年3月19日)や新機能もWebページ上で公開 されています。
現時点で予定されている新機能は、下記の8つです。
開発関連
JVM関連
GC関連
ツール関連
とくに開発者が最初に押さえておきたい新機能は、JEP 325のswitch構文の拡張 です。switch構文内において、local変数を定義可能になっている他、 switch構文の処理結果を新しい変数に代入するような構文が追加されています。これにより、今まで記述できなかった書き方ができるようになっています。
また、下記の例に記載しているように、switch文の演算子として「->(arrow operator) 」が利用できるようになっています。 詳細はJEP 325をご参照ください。
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
それ以外で筆者が注目しているのは、JEP 310(JDK 10) 、JEP 341(JDK 11)など、Class Data Sharing(CDS)機能に対する改善です。Function as a ServiceやDockerなどのコンテナ環境で、Javaアプリケーションを高速に起動したいニーズがあります。これを改善するためにJDK 8u40以降でCDSに対していくつか改善されています。
実際に、JRubyのアプリケーションで30%高速に起動できるようになったというデータがある他、アプリケーションによっては 50%の高速化も可能です。Javaの起動時間が遅いと感じる方は、ぜひ、Class Data Sharingをお試しください。
その他、Java VMやGCでも改良が入っているため、コンテナ環境でJavaを扱う筆者は、OpenJDK 12 のリリースを心待ちにしています。
最後に
時代の流れはめまぐるしく、日々新しいテクノロジやフレームワークが生まれてきています。1年前は新しかった技術が1年後はあたりまえになったり、もしくは廃れている場合もあります。Javaのエンジニアとして今まで蓄えてきたノウハウや技術は、いつ古くなったり時代遅れになるかもしれません。
今の時代、勉強をやめた時点でエンジニアとしての人生が終わるといっても過言ではありません。現在の状況に満足せずに、エンジニアとして成長していくためにも、つねに業界の動向をウォッチし、新しいことにもチャレンジしながらJavaのエンジニアとして成長していきましょう!!
結果として、日々成長するエンジニアや、より優秀なエンジニアが、より良い環境で、より良い報酬を得て幸せに働ける日が来ることを願っています。