Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java SE 8から11で何が起きた?一気におさらいしてみよう! /java-se-8-to-11

Java SE 8から11で何が起きた?一気におさらいしてみよう! /java-se-8-to-11

Introduces changes in Java SE and its ecosystem, from Java SE 8 to 11.

Miyakawa Taku

December 23, 2018
Tweet

More Decks by Miyakawa Taku

Other Decks in Programming

Transcript

  1. 本セッションのあらまし ⚫ Java SE 8からJava SE 11に掛けて、 たくさんのことが起こりました ◼ JDKのリリースモデル変更

    ◼ モジュールシステムの導入 ◼ 各種機能の追加・変更・廃止・切り離し ⚫ 何が起きたのか把握して、 安心して11+に踏み出しましょう☆ ⚫ とはいえ #javajo 3/137
  2. 本セッションの基調低音 ⚫ Javaは変わりつつある ⚫ Write Once Run Anywhereの担い手という 役割は縮小している ⚫

    一方で、サーバサイド処理系としての 進化はペースを上げている #javajo 5/137
  3. スコープ 主に触れること ◼ Java処理系関連のざっくりした傾向 ◼ モジュール関連の機能 触れないこと ◼ 実装固有の機能: GC,

    内部処理改善等 ◼ 外部ツール・ライブラリの対応状況 → Migration Guide from Java 8 to Java 11 by 久保田さん #javajo 7/137
  4. Java SEとは Java SE: Java処理系の規格 ◼ 正式名称: Java Standard Edition

    ◼ 規格の中身: ◆ 言語仕様 ◆ Java仮想マシンの仕様 ◆ 標準APIの仕様 ◼ 代表的な実装: OpenJDK, Oracle JDK等 #javajo 10/137
  5. Java SEタイムライン invokedynamic ラムダ式, Stream API モジュール・システム (a.k.a. Jigsaw) 2011.07

    Java SE 7 2014.03 Java SE 8 2017.09 Java SE 9 2018.03 Java SE 10 var記法 Functional Java 基盤の大改造 2018.09 Java SE 11 Appletの削除 ServiceLoader 2006.12 Java SE 6 #javajo 11/137
  6. Java SEの規格開発プロセス Java Community Process (JCP) ◼ 正式な規格化プロセス ◼ Expert

    Groupによるドラフト提出、 Executive Committeeの投票を通して、 個々の仕様であるJSRを策定 ◼ Java MEやEEも対象(だった) ◆ Jakarta EEは対象外 ◼ きっちりしたはる #javajo 12/137
  7. Java SEの規格開発プロセス JDK Enhancement Proposal (JEP) ◼ OpenJDKの開発プロセス ◼ 主にML内で合意形成される

    ◼ Python Enhancement Proposalがお手本 ◼ 2011年以降、実質的にはJEPが規格化を 引っ張る ◼ Java SEの規格に入らない、実装固有の 機能(例: GC方式)も議論の対象 #javajo 13/137
  8. List.of List<String> a = Collections.emptyList(); List<String> b = Collections.singletonList("foo"); List<String>

    c = Collections.unmodifiableList(Arrays.asList("foo", "bar")); List<String> a = List.of(); List<String> b = List.of("foo"); List<String> c = List.of("foo", "bar"); ~Java SE 8 Java SE 9~ #javajo 17/137
  9. Map.of Map<String, Integer> m = new HashMap<>(); m.put("双葉山", 69); m.put("大鵬",

    45); m.put("白鵬", 63); Map<String, Integer> yokozuna = Collections.unmodifiableMap(m); ~Java SE 8 Map<String, Integer> yokozuna = Map.of("双葉山", 69, "大鵬", 45, "白鵬", 63); Java SE 9~ #javajo 18/137
  10. try-with-resourcesの改善 try (BufferedReader br = new BufferedReader( new InputStreamReader( new

    FileInputStream("foo.txt"), StandardCharsets.UTF_8))) { ... } ~Java SE 8 Java SE 9~ BufferedReader br = new BufferedReader( new InputStreamReader( new FileInputStream("foo.txt"), StandardCharsets.UTF_8)); try (br) { ... } #javajo 20/137
  11. ResourceBundle→UTF-8 ~Java SE 8 Java SE 9~ ⚫ ResourceBundleのプロパティファイルは デフォルトでLatin-1

    ⚫ 日本語などのメッセージはnative2asciiで エスケープする必要があった ⚫ ResourceBundleのプロパティファイルが デフォルトでUTF-8に☆ ⚫ 注意: Propertiesクラスのデフォルトは Latin-1のまま #javajo 22/137
  12. var記法 var トリオ漫才 = List.of( "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー"); トリオ漫才.forEach(System.out::println); Java

    SE 10, 11 List<String>トリオ漫才 = List.of( "横山ホットブラザーズ", "かしまし娘", "宮川左近ショー"); トリオ漫才.forEach(System.out::println); Java SE 9 ローカル変数宣言で型が省略できるように #javajo 24/137
  13. サーバ向け機能の削除 Java SE 11で削除された主なサーバ向け機能: ◼ ドロップインの代替ライブラリあり ◆ JAXBのAPIとデフォルト実装 ◆ JAX-WSのAPI

    ◆ JTAのAPI ◼ ドロップインの代替ライブラリなし ◆ CORBA → 該当機能を使用中の場合、移行時に要対応 #javajo 26/137
  14. デスクトップ向け機能の削除 Java SE 11でApplet*が削除 ◼ 主要ブラウザはNPAPI廃止済みのため、 既に使えなくなっていた ◼ ブラウザプラグイン自体が下火 Flash,

    Silverlightも廃止予定 ◼ HTML5時代の必然 #javajo * Applet: ブラウザプラグイン上で動く Java プログラム。 Flashみたいな感じ 28/137
  15. デスクトップ向け機能の削除 Oracle JDK 11はJavaFX*1とJava Web Start*2 を同梱しなくなった ※ 両方もともとJava SE仕様範囲外

    ※ ただしWeb Startには関連仕様として JSR 56: JNLPがある ◼ JavaFXはOpenJFXプロジェクトで 開発継続中 #javajo * 1 JavaFX: GUIライブラリ。 SwingとかQtみたいなやつ * 2 Java Web Start: リンクを押すと Java プログラムが 落ちてきてPC上 で実行される仕組み 29/137
  16. Java SEをとりまく環境の変化 Java SE 8から11にかけての大変動: ◼ OpenJDK, Oracle JDKの リリースサイクル変更(Java

    9~) ◼ Oracle JDKのライセンス変更 (Java 11~) ◼ Public JRE配布の廃止 (Java 11~) ◼ OpenJDKエコシステムの活発化 #javajo 32/137
  17. リリースサイクル変更 ~Java SE 8 Java SE 9~ 2006.12 Java SE

    6 2011.07 Java SE 7 2014.03 Java SE 8 4 年半 2 年半 2017.09 Java SE 9 2018.03 Java SE 10 2018.11 Java SE 11 2019.03 Java SE 12 2019.11 Java SE 13 仕様が固まったら リリース 半年ごとに リリース #javajo 34/137
  18. Oracle JDKのライセンス変更 Java 11~ ◼ OTNライセンスに変更 ◆ 開発用途の利用はOK ◆ 本番用途はダメ

    ◼ 本番用途でOracle JDKを使うには、 サブスクリプションの契約が必要 ※ 3年ごとのLTS版(11, 17, ...)に、 半年を超えてパッチが提供される #javajo 38/137
  19. WORA! ⚫ Javaのプログラムはどこでも動く Write Once, Run Anywhere! ⚫ OSがUnixでもWindowsでも ⚫

    CPUがx86でもSparcでもARMでも ⚫ ただし、Javaがインストールされていれば #javajo 41/137
  20. WORAの前提としてのPublic JRE ⚫ Public JREは、一般ユーザ向けに Sun/Oracleが配布していたJava処理系 ◼ 「あなたとJAVA, 今すぐダウンロード」 ⚫

    AppletプラグインやJava Web Startも含む → いずれもJava SE 11で廃止 ⚫ Java SE 11では、 Public JREの配布が廃止された #javajo 42/137
  21. OpenJDK OpenJDK (https://openjdk.java.net/) ◼ Java SEの参照実装(RI) ◼ ライセンス: GPLv2+Classpath Exception

    ◼ コントリビュータ: ◆ Oracle, Red Hat, IBM, Azul, Amazon .. ◆ @YaSuenag, @sugarlife, @shinyafox .. ◼ Oracle JDKの商用機能が多くマージされ、 ほぼ同じ中身になった #javajo 47/137
  22. 開発の加速 加速するOpenJDK開発 ◼ たくさんの新GC方式 ◆ G1GC, ZGC, Shenandoah ◼ 起動時間の改善

    ◆ Class Data Sharing, AOT Compilation ◼ フットプリント削減: jlink ◼ 新JITコンパイラ: Graal ◼ 新仕様群: Panama, Vallhara, Loom, ... #javajo 48/137
  23. #javajo Red Hat OpenJDK ⚫ Red HatによるOpenJDKパッケージ ⚫ GC実装としてShenandoahが含まれる ⚫

    Red Hat Enterprise Linux, Windows ⚫ 提供バージョンを最短6年アップデート ⚫ 商用サポートあり 52/137
  24. #javajo Azul Zulu ⚫ Zulu ⚫ Java処理系専業企業であるAzul Systemsが 提供するディストロ ⚫

    Windows (x86-64), Mac, Linux (x86-64, ARM64) ⚫ LTS版について8年アップデート ⚫ 商用サポートあり 53/137
  25. #javajo Amazon Corretto ⚫ Amazon Corretto ⚫ Amazon Linuxにバンドルしていた OpenJDKをパッケージ化したもの

    ⚫ Windows (x86, x86-64), Mac, Linux (x86-64) ⚫ 2018年12月時点でOpenJDK 11は未提供 54/137
  26. ~Java 8: JAR地獄 ⚫ JAR地獄 := 大量のJARがクラスパスに 展開されて、混沌にブチ込まれること ◼ 「このJARいらないんじゃない?」

    ◼ → 消したら実行時エラー ⚫ Maven, Gradleのような依存性管理 ツールを使えば少しはマシだけど…… #javajo 66/137
  27. ~Java 8: JAR地獄 複数バージョン混在地獄 ゲ ー ム Ace Shooter matrix-1.0.0.jar

    matrix-impl-2.0.0.jar matrix-api-2.0.0.jar physics.jar 名前の異なるMavenアーティファクトが 同じパッケージ/クラスを含む場合があり得る org.example.matrix.api.* org.example.matrix.impl.* org.example.matrix.api.* org.example.matrix.impl.* #javajo 67/137
  28. ~Java 8: 内部向けパッケージ ⚫ プラットフォームやライブラリ内で、 「内部向け」パッケージを作ることがある ◼ org.kink_lang.kink.internal.xxx ◼ sun.misc

    (JDK内) ⚫ 内部向けパッケージは本来、ライブラリ外 からの使用を想定していない ⚫ が、しかし #javajo 69/137
  29. ~Java 8: 内部向けパッケージ ⚫ 内部使用向けのはずのUnsafeクラスが広く 使われてしまっている ◼ 性能を絞り出すため…… ⚫ なにが問題か?

    ◼ 移植性の低いプログラムの蔓延 ◼ 既存のプログラムを壊さないように配慮 すると、実装の改善がしづらい #javajo 72/137
  30. ~Java 8: Java処理系の肥大化 #javajo 42MB 68MB 146MB 177MB Java SE

    5 Java SE 6 Java SE 7 Java SE 8 Oracle JDKのダウンロードサイズ ※いずれもx86-64版の最新バージョン 76/137
  31. パッケージ衝突の検知 module net.example.ace_shooter module org.example.matrix module org.example.matrix.impl module org.example.matrix.api module

    jp.example.physics 複数のモジュールが同一パッケージを含む場合、 起動時に検知される † org.example.matrix.impl.* org.example.matrix.api.* org.example.matrix.api.* org.example.matrix.impl.* #javajo 81/137
  32. 使うモジュールの指定 module jp.example.physics { requires org.example.matrix; } モジュールは、自分が使うモジュールを、 requires命令で指定する モジュールが使えるクラスの条件:

    ⚫ requiresした先のモジュールの ⚫ exportsされたパッケージの ⚫ publicなクラス → 該当しないクラスを使うと コンパイルエラー / 実行時例外 #javajo 84/137
  33. exports / requires module A { requires B; } module

    B { exports B.api; requires C; } module C { exports C.api; } B.apiパッケージ B.implパッケージ C.apiパッケージ →使える →使えない →使えない C.apiパッケージ →使える #javajo 85/137
  34. exports / requires module A { requires B; } module

    B { exports B.api; requires C; } module C { exports C.api; } A.xxxパッケージ →使える 自分のモジュール内のパッケージは、非公開でも使える B.xxxパッケージ C.xxxパッケージ →使える →使える #javajo 86/137
  35. exports / requires module A { requires B; } module

    B { exports B.api; requires C; } requiresしたモジュールが存在しないと コンパイルエラー / 実行時例外 #javajo 87/137
  36. リフレクション 困る例: DI先のクラス package net.example.ace_shooter.engine; public class GameEngine { @Inject

    private PerfMonitor perfMonitor; ... } public にしたくない exportsしたくない リフレクションで触ってほしいクラスは 必ずしも公開したいわけではない #javajo 91/137
  37. コンパイル javacコマンドの主なオプション オプション 内容 --module-path ¥ {モ ジ ュ ー

    ル パス} 依存先モジュールの配置場所 --module-source-path ¥ {モジュールソースパス} 複数モジュールを同時コンパイル する時、モジュールのソースディ レクトリの配置場所 ※あまり使わないはず --module-version ¥ {バ ー ジ ョン} モジュールのバージョン ※いまのところ使い道は無い #javajo 99/137
  38. 実行 javaコマンドの主なオプション オプション 内 容 --module-path ¥ {モ ジ ュ

    ー ル パス} モ ジ ュ ー ル の 場 所 --module ¥ {初 期 モ ジ ュ ー ル名}/{メインクラス } mainメソッドを持つ ク ラ ス --module {初期モジュール 名} 初 期 モ ジ ュ ー ル --add-modules ¥ {モ ジ ュ ー ル名},{モジュール名},... 指定したモジュール を ブ ー ト レ イ ヤ ー に 追 加 #javajo 101/137
  39. 無名モジュール ⚫ クラスパス上のクラスファイルは、 無名モジュールの中でロードされる ⚫ 無名モジュールは: ◼ モジュール名を持たない ◼ すべてのモジュールをrequiresする

    ◼ すべてのパッケージをexportsする ◼ (Java SE実装依存)外部モジュールの 非公開メンバへのリフレクションが可能 #javajo ‡ 104/137
  40. モジュール世界への移行 ソフトウェア種別ごとのモジュール化指針: 種別 モジュール化指針 ライブラリ いますぐモジュール化! プラグイン 基盤ミドルウェア次第 APサーバ上の アプリケーション

    基盤ミドルウェア次第 ※Java EE 8はモジュール非対応 スタンドアロンの アプリケーション 遅くなりすぎない程度に モジュール化する場合もしない場合も、 JDK9への移行ガイドは必読 #javajo 108/137
  41. ライブラリのモジュール化 JARファイル名ベースの自動モジュールを requiresしてはいけない! module org.example.matrix { requires commons_io; ... }

    駄目パターン: → Commons IOに本当のモジュール名が 付いたとき、ライブラリを使う側のプログラムが 不整合になる ※ requires staticは許容範囲 #javajo 110/137
  42. モジュールのテスト 二種類のテスト ブ ラ ッ ク ボ ッ ク ス

    ・テスト ⚫ モ ジ ュ ー ル の 外 か ら テ スト 。 ⚫ exportsされたパッケージの、public な ク ラ ス を 操 作 し て 、 仕 様ど お りに 動 く こ と を 確 か め る 。 ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と 別 モ ジ ュ ー ル 。 ホ ワ イ ト ボ ッ ク ス ・テスト ⚫ モ ジ ュ ー ル の 内 側 を テ スト 。 ⚫ 公 開・非公開にかかわらず、クラ ス・ メソッドを操作して、意図した実装に な っ て い る こ と を 確 か める 。 ⚫ テ ス ト コ ー ド は 、 テ ス ト対 象 と 同 一 モ ジ ュ ー ル……どうやって? #javajo 114/137
  43. モジュール定義の上書き JDKのjavac/javaコマンド共通オプション オプション 内 容 --add-reads ¥ {モ ジ ュ

    ー ル名}={参照先モジュール},... requires定義を追加 --patch-module ¥ {モ ジ ュ ー ル名}={ファイル,...},... モ ジ ュ ー ル に ソ ー ス フ ァ イ ル/クラス フ ァ イ ル を 追 加 #javajo 117/137
  44. モジュール定義の上書き javac ... ¥ --add-reads app=junit ¥ --patch-module app=ATest.java,BTest.java java

    ... ¥ --add-reads app=junit ¥ --patch-module app=ATest.class,BTest.class ¥ --add-modules ALL-MODULE-PATH コンパイル 実行 モ ジ ュ ー ル パ ス 上 の 全JARを実行構成に含める #javajo 118/137
  45. 基本的な使い方 #javajo jlink --module-path build/jars ¥ --add-modules jp.example.hoge,org.slf4j.simple ¥ --launcher

    cmd=jp.example.hoge/jp.example.hoge.main.Main ¥ --output build/pkg build/pkg: カスタムJava処理系 build/pkg/lib: モジュール、ネイティブライブラリ等 build/pkg/bin: コマンド 122/137
  46. 主なコマンドラインオプション #javajo オプション 内容 --module-path {モ ジ ュ ー ル

    パ ス} モジュールを探す場所 --add-modules ¥ {モ ジ ュ ー ル1},{モジュール2},... 処理系に追加する モジュールの起点 --bind-services SPIの実装を提供するモ ジュールも処理系に含む --launcher { コ マ ン ド 名 }={初期 モジュール }/{メインクラス} mainメソッドを持つクラ ス --launcher { コ マ ン ド 名 }={初期 モジュール } 初期モジュール --output {出力先ディレクトリ} 処理系の出力先 123/137
  47. ブートレイヤー モジュールレイヤー モジュールレイヤー: モジュールの名前空間 java.base java.sql jp.example.app_container java.desktop java.logging アプリ

    X のレイヤー アプリ Yのレイヤー com.example.app_x org.example.app_y net.example.utils net.example.utils 子 親 子 親 アプリケーションサーバや、プラグイン機構の 基礎となる仕組み #javajo 130/137
  48. † パッケージの衝突検知 「複数のモジュールが同一パッケージを含む場 合、起動時に検知される」 ◼ 厳密には、「モジュールレイヤーが、モ ジュール間のパッケージ重複を許さない構 成である時、そのモジュールレイヤー内の 複数のモジュールが~」である ◼

    異なるモジュールレイヤー間では、同じ名 前のパッケージが共存できる ◼ defineModulesWithManyLoadersで作られた モジュールレイヤーは、exportされない パッケージの重複を許す #javajo 136/137
  49. ‡ 強固なカプセル化の緩和 「(Java SE実装依存)外部モジュールの非公 開メンバへのリフレクションが可能」 ◼ Java SE 9仕様(JSR 379)では、Java

    SE実装が、このような動作をデフォル トとしてもよい、と規定されている (Relaxing strong encapsulation節) #javajo 137/137