Contents
- 1 導入
- 2 この記事の構成
- 3 主要な変更点と実務影響(抜粋)
- 3.1 JEP 403 — Strongly Encapsulate JDK Internals(影響度: 高)
- 3.2 JEP 409 — Sealed Classes(影響度: 中)
- 3.3 JEP 406 — Pattern Matching for switch(Preview)(影響度: 中)
- 3.4 JEP 356 — Enhanced Pseudo-Random Number Generators(影響度: 低〜中)
- 3.5 JEP 382 — New macOS Rendering Pipeline (Incubator)(影響度: 低〜中)
- 3.6 JEP 391 — macOS/AArch64 Port(影響度: 中)
- 3.7 JEP 398 — Deprecate the Applet API for Removal(影響度: 低〜中)
- 3.8 JEP 411 — Deprecate the Security Manager for Removal(影響度: 中)
- 3.9 JEP 306 — Restore Always-Strict Floating-Point Semantics(影響度: 中)
- 4 言語仕様/APIの重要追加と実務的利用例(コード例)
- 5 互換性チェックの実務手順(CI で回す項目)
- 6 ビルド/CI/コンテナ運用の実務対応
- 7 運用上の注意点と推奨方針
- 8 移行チェックリスト(優先度別)
- 9 よくある質問(FAQ)
- 10 参考リンク(一次情報優先)
導入
Java 17(JDK 17)は LTS(Long-Term Support)版であり、企業システムの基盤更新先として現実性が高い選択です。本記事は Java 17 の主要な変更点と、実務での影響・優先対応点を整理します。CI・ビルド・コンテナ運用を含む具体手順と段階的な移行チェックリストを提示し、移行判断と実作業の入り口を明確にします。まずは CI に JDK 17 のジョブを並列追加して互換性を早期に検出してください。
この記事の構成
この記事は実運用で即使える情報を優先して構成しています。各セクションは結論と理由、具体手順を含めて短くまとめています。重要箇所を素早く確認したい場合は「主要な変更点」「CI/ビルド」「移行チェックリスト」を先に参照してください。
- 主要な変更点と実務影響(JEP の抜粋と優先度)
- 言語仕様/API の採用方針と実務的コード例
- 互換性チェックの自動化手順(CI で回す項目)
- ビルド/CI/コンテナ運用の実務対応(Maven/Gradle/Docker)
- 運用上の注意点(プレビュー方針、macOS/AArch64、ライセンス)
- 移行チェックリスト(優先度別)と FAQ
- 参考リンク(一次情報優先)
主要な変更点と実務影響(抜粋)
ここでは「導入判断に影響する変更」を網羅基準として重要な JEP を抜粋します。詳細は各 JEP ページと JDK のリリースノートで一次情報を必ず確認してください。
JEP 403 — Strongly Encapsulate JDK Internals(影響度: 高)
JDK の内部パッケージへの反射アクセスが原則禁止されます。互換性とセキュリティで最大のリスク源です。
- 検出方法: jdeps で依存を洗い出す(例: jdeps --jdk-internals target/myapp.jar)。
- 典型的な実行時エラー:
- java.lang.reflect.InaccessibleObjectException(反射で setAccessible 等が失敗した場合に多い)
- IllegalAccessError(リンク時や互換性崩壊で発生する場合がある)
- NoSuchMethodError / NoClassDefFoundError(内部クラス削除や署名変更の影響)
- ※違いの目安: InaccessibleObjectException は反射 API によるアクセス拒否を示す実行時例外で、IllegalAccessError はバイナリ互換性/リンク時の問題を示す Error であることが多いです。
- 短期対応: --add-opens=モジュール/パッケージ=ALL-UNNAMED を一時利用して動作確認する(例: --add-opens java.base/java.lang=ALL-UNNAMED)。
- 恒久対応: 依存ライブラリの更新、JDK 公開 API への移行、またはモジュール記述子の見直し。
JEP 409 — Sealed Classes(影響度: 中)
継承を許可するサブタイプを明示でき、API の意図を明確化できます。シリアライズやフレームワーク側の取り扱いに注意が必要です。
- 利点: API 設計の安全性向上、switch の網羅検査との親和性。
- 検討事項: シリアライズ対応、リフレクションや DI フレームワークでの扱い確認。
JEP 406 — Pattern Matching for switch(Preview)(影響度: 中)
switch 式でのパターンマッチを導入するプレビュー機能です。採用には注意が必要です。
- 実行条件: コンパイル・実行ともに --enable-preview が必要。
- 採用方針は別セクションで統合して提示します(プレビュー機能の採用方針参照)。
JEP 356 — Enhanced Pseudo-Random Number Generators(影響度: 低〜中)
RandomGenerator API と複数アルゴリズムを提供します。非暗号用途での移行メリットがあります。
- 暗号用途では SecureRandom を継続して使用すること。
- 移行時はシード互換性/順序の違いに注意し、ベンチマークで性能比較する。
JEP 382 — New macOS Rendering Pipeline (Incubator)(影響度: 低〜中)
Metal ベースの Java2D 描画パイプライン。UI 表示の差異検証が必要です。
JEP 391 — macOS/AArch64 Port(影響度: 中)
Apple Silicon(AArch64)向けのネイティブサポート。CI やステージで macOS/AArch64 を検証してください。
JEP 398 — Deprecate the Applet API for Removal(影響度: 低〜中)
Applet API の非推奨化。古いブラウザ連携コードの検出と置換を行ってください。
JEP 411 — Deprecate the Security Manager for Removal(影響度: 中)
SecurityManager の非推奨化。コンテナやOSレベルの隔離、RBAC など代替手段の検討が必要です。
JEP 306 — Restore Always-Strict Floating-Point Semantics(影響度: 中)
浮動小数点の厳密モードを復元します。数値計算の結果差分に注意し、回帰テストを実行してください。
言語仕様/APIの重要追加と実務的利用例(コード例)
以下は採用判断と実装上の注意を含むサンプルです。各小トピックは使いどころと注意点を短く示します。
Sealed classes の例
Sealed classes は API の許容派生クラスを制限し、設計の意図を明確化します。シリアライズやフレームワークの互換性を確認してください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public sealed interface Shape permits Circle, Rectangle {} public final class Circle implements Shape { private final double radius; public Circle(double radius) { this.radius = radius; } public double radius() { return radius; } } public final class Rectangle implements Shape { private final double width, height; public Rectangle(double w, double h) { width = w; height = h; } public double area() { return width * height; } } |
Pattern matching for switch(プレビュー利用)
プレビュー機能はコンパイル/実行時に --enable-preview が必要です。CI に組み込む場合は全てのビルドジョブでフラグを明示してください。
|
1 2 3 4 5 6 7 8 9 10 11 |
public class SwitchDemo { public static String describe(Object o) { return switch (o) { case Integer i -> "int: " + i; case String s -> "str: " + s; case Shape sh -> "shape: " + sh.getClass().getSimpleName(); default -> "other"; }; } } |
コンパイル/実行例(JDK 17、プレビュー利用):
- javac --enable-preview --release 17 SwitchDemo.java
- java --enable-preview SwitchDemo
RandomGenerator(JEP 356)の利用例
非暗号用途での移行が有効です。シード互換が必要な箇所は注意してください。
|
1 2 3 4 5 6 7 8 9 10 |
import java.util.random.RandomGenerator; import java.util.random.RandomGeneratorFactory; public class RNGDemo { public static void main(String[] args) { RandomGenerator rng = RandomGeneratorFactory.getDefault().create(); System.out.println(rng.nextInt(100)); } } |
ビルドツールとプラグインのバージョン例
Maven と Gradle の最低限のバージョン・プラグイン例を示します。環境再現のため、ディストリ・バージョンは固定タグやダイジェストで管理してください。
- Maven: Maven 3.6+ を推奨(3.8+ が望ましい)。maven-compiler-plugin は 3.8.1 以上、推奨 3.10.x。maven-surefire-plugin は 2.22.2 以上、3.0.0 系を推奨。
- Gradle: Gradle 7.3+ を推奨(Java Toolchains を安定的に使うため)。Gradle Wrapper の固定を必須としてください。
Maven の設定例(プラグインバージョンを明示):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <release>17</release> <compilerArgs> <arg>--enable-preview</arg> </compilerArgs> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0</version> <configuration> <argLine>--enable-preview</argLine> </configuration> </plugin> |
Gradle の設定例(Gradle 7.3+):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } tasks.withType(JavaCompile).configureEach { options.release = 17 options.compilerArgs += '--enable-preview' } test { jvmArgs += '--enable-preview' } |
Docker イメージの運用上の注意
ディストリビューションやタグ名はベンダーにより異なるため、必ず固定タグあるいはダイジェストで管理してください。例:
- ビルドステージ: FROM eclipse-temurin:17-jdk (ベンダー・バージョン固定を推奨)
- ランタイムステージ: FROM eclipse-temurin:17-jre または vendor の slim 版
マルチディストリ間では glibc/musl の差分やライブラリ互換に注意してください。SBOM を生成してサードパーティ依存を可視化してください。
互換性チェックの実務手順(CI で回す項目)
互換性は静的解析→CI 並列検査→ステージでの AB 検証の順で検出・対処します。ここでは CI に組み込むべき具体的項目を示します。
CI マトリクス化と実行ポリシー
CI で現行と並列にテストを回し、差分を早期検出します。短いスモークは PR レベル、フルスイートは Nightly に振り分けます。
- 例: matrix: [8, 11, 17] を回す(GitHub Actions 等)。
- PR: 単体・スモークテスト、Nightly: 統合・パフォーマンス。
- プレビュー機能を利用するジョブは明示的にフラグを渡す。
静的解析
静的で検出可能な互換性問題を自動化します。
- jdeps(JDK 付属): jdeps --jdk-internals target/myapp.jar で内部 API 依存を検出。
- japicmp / Revapi: API 互換性の差分検出。
- animal-sniffer: 古い API 利用の検出。
- 依存グラフ解析: mvn dependency:tree / gradle dependencies で古い JAR を排除。
ランタイム検査とログ収集
ステージでの実行時に発生する例外や動作差分を検出します。
- 監視対象例外: InaccessibleObjectException、IllegalAccessError、NoSuchMethodError、ClassNotFoundException。
- ログ収集: CI に JFR/GC ログ・スタックトレースを保存して差分を自動解析する。
- 短期回避の記録: --add-opens を使用したジョブはフラグ付きで記録し、恒久対応チケットを作成。
必須テスト項目
各カテゴリでのテストを CI に組み込みます。
- 単体テスト・統合テスト(全機能)
- シリアライズ互換テスト(serialVersionUID、バイト互換)
- ネイティブ/JNI テスト(実機必須)
- UI 回帰(Java2D の差分、macOS の Metal パイプラインを含む)
- パフォーマンス(JMH): スループット、レイテンシ、GC、ヒープ使用量比較
- 起動時間・メモリ RSS 比較、定期的なスレッドダンプ・ヒープダンプ取得
検証フロー(推奨)
CI(並列検査) → ステージ(AB 検証) → カナリア(限定トラフィック) → 本番ローリング。メトリクスはエラー率・レイテンシ・GC パターン・CPU/メモリを重点的に監視してください。
ビルド/CI/コンテナ運用の実務対応
ビルドやコンテナ運用で実践すべき設定と運用ルールを示します。再現性と可視化を優先してください。
Maven/Gradle の運用ポイント
Maven と Gradle での推奨設定をまとめます。
- Maven: pom.xml に maven-compiler-plugin バージョンを明示し
17 を設定。surefire/failsafe に argLine を渡す。CI では setup-java 等で JDK を安定供給。 - Gradle: Java Toolchains を使い languageVersion = 17 を指定。Gradle Wrapper 固定。Gradle 7.3+ を推奨。
- いずれもプレビュー利用時はコンパイル・テスト・実行すべてで --enable-preview を付与。
コンテナイメージ運用
コンテナ運用のベストプラクティスです。
- マルチステージビルドでビルド環境と実行環境を分離。
- イメージは固定タグかダイジェストで管理。例: eclipse-temurin:17-jdk といったタグはベンダーにより命名規則が異なるためバージョン・ディストリ名を明示的に管理。
- 実行は非 root、SBOM を生成して依存を可視化。
- 主要ディストリ: Eclipse Temurin(Adoptium)、Amazon Corretto、BellSoft Liberica、Azul Zulu など。用途によりサポート期間と商用サポートの有無を確認すること。
CI パイプライン設計例(要点)
- PR: 速いスモークテスト(ユニット・静的解析)
- Merge/Nightly: 統合テスト・JMH ベンチ・セキュリティスキャン
- Stage: AB テスト用デプロイ・ログ/メトリクス集約
- 本番: カナリアからローリングデプロイ、旧イメージを保持して即時ロールバック可能にする
運用上の注意点と推奨方針
移行中・移行後に運用チームが守るべき方針と具体的手段をまとめます。プレビュー機能の扱いは一箇所で統一して示します。
プレビュー機能の採用方針(統合)
プレビュー機能は段階的に採用します。開発・検証環境で十分にテストし、CI で常にフラグを付けたビルドを回してください。
- 採用ルール例:
- 開発ブランチで実験 → Nightly でフルテスト → ステージで限定採用 → 本番は安定後に限定導入。
- プレビュー API を利用するコードには TODO/TICKET を紐付け、将来の標準化・仕様変更に備える。
- CI は全ビルドで --enable-preview の有無を明示的に設定し、差分ログを残す。
macOS/AArch64 の CI 検証手段とコスト感
macOS/AArch64(Apple Silicon)での検証は必須です。主な選択肢と概算の目安を示します。
- 自前実機(Mac mini M1/M2): 一回の投資で約 600〜1200 USD 程度(概算)。短期的にコスト効率が良く、セルフホストランナーとして安定利用可能。
- マネージドレンタル(例: MacStadium 等): 月額で数十〜数百 USD。管理負荷を下げたい場合に有効。
- CI ベンダーのホスト(GitHub Actions / CircleCI 等): macOS ホストランナーは分単位で課金されるため、ビルド頻度が高い場合はコストが膨らむ。arm64(Apple Silicon)のホスト提供状況はベンダーにより異なるため事前確認が必要。
- クラウド(AWS EC2 Mac 等): ハードウェア要件や料金体系が特殊。長時間実行のワークロード向け。
選定の指標: ビルド頻度(高→自前 or 専用レンタル)、運用負荷(低→マネージド)、コスト(短期はクラウドスポットや分課金を活用)。
セキュリティ/ライセンスの注意点
ベンダーごとにサポート期間や商用サポートの有無が異なります。配布や商用利用のポリシーを確認してください。
| ベンダー(例) | 商用利用 | 長期サポート | 備考 |
|---|---|---|---|
| Eclipse Temurin (Adoptium) | 可(無料ビルド) | コミュニティ/複数ベンダーでサポート | 商用サポートは別契約で提供される場合あり |
| Amazon Corretto | 可(無料) | 長期サポート方針あり | AWS によるビルド・サポート |
| BellSoft Liberica | 可(無料ビルド) | 商用サポートあり | エンタープライズ向けサポートあり |
| Azul (Zulu/Prime) | 可(Zuluは無料) | 商用サポート(Azul Platform)あり | 長期サポートプランあり |
注意: 具体的なサポート期間やライセンス条件はベンダーの公式ページで確認してください。
移行チェックリスト(優先度別)
ここでは優先度付きで段階的に実行するチェック項目を示します。各小見出しの冒頭に優先度の説明を付けています。
優先度 — 高(まず必ず実施)
重要影響を持つ項目に優先的に着手してください。
- CI に JDK 17 ジョブを追加して並列でビルド・テストを実行する。
- jdeps で内部 API 依存を検出し、高リスクライブラリを特定する。
- 重要ライブラリ(データアクセス、認証、ネイティブ)を最新安定版に更新する。
- 自動化されたユニット・統合テストのカバレッジを確保する。
- ネイティブ/JNI 部分は実機での回帰検証を確保する。
優先度 — 中(並行して対応)
機能影響・運用影響が中程度の項目です。
- パフォーマンスベンチ(JMH)で既存挙動と比較し、差分があればチューニング。
- Java2D/UI 描画の差分を macOS(AArch64 含む)で検証。
- SecurityManager 依存箇所の代替設計(コンテナ・OS ポリシー)を検討する。
- シリアライズ互換(serialVersionUID)を重点的に確認する。
優先度 — 低(導入後に順次対応)
リスクが低い、あるいは段階的に取り組める項目です。
- ライブラリの API の最新機能(Sealed、RandomGenerator 等)への段階的移行。
- プレビュー機能の試験導入・評価。
- SBOM の定期更新と脆弱性スキャンの強化。
よくある質問(FAQ)
この節では実務でよく出る疑問に短く回答します。
Q: 既存 JAR の再コンパイルは必要ですか?
A: 多くの場合は不要です。Java はバイナリ互換性が高いため実行時に問題が出るかで判断します。問題が出れば再コンパイルや依存更新が必要です。
Q: プレビュー機能を本番で使えますか?
A: 原則慎重にしてください。仕様変更リスクがあるため、段階的に導入し CI で常時テストする場合に限定的に採用することを推奨します。
Q: 反射アクセスでエラーが出た場合、まず何をすべきですか?
A: まず依存ライブラリを最新版に更新し、それでも解決しない場合は一時的に --add-opens で動作を確認します。恒久的には内部 API 依存の除去が必要です。
Q: macOS/AArch64 の CI 検証はどうすれば良いですか?
A: 自前の Mac mini、マネージドレンタル(MacStadium 等)、あるいは CI ベンダーのホスト(提供状況を要確認)を検討してください。頻度や運用負荷に応じて選定します。
参考リンク(一次情報優先)
移行判断・技術的詳細は必ず一次情報で確認してください。下記は主要な公式ページです。
- OpenJDK JDK 17 プロジェクトページ: https://openjdk.java.net/projects/jdk/17/
- JDK リリースノート(OpenJDK): https://openjdk.org/ (該当リリースノートを参照)
- 各 JEP ページ(例):
- JEP 356: https://openjdk.java.net/jeps/356
- JEP 382: https://openjdk.java.net/jeps/382
- JEP 391: https://openjdk.java.net/jeps/391
- JEP 398: https://openjdk.java.net/jeps/398
- JEP 403: https://openjdk.java.net/jeps/403
- JEP 406: https://openjdk.java.net/jeps/406
- JEP 409: https://openjdk.java.net/jeps/409
- JEP 411: https://openjdk.java.net/jeps/411
- ベンダー公式ダウンロード/情報:
- Eclipse Temurin (Adoptium): https://adoptium.net/
- Amazon Corretto: https://aws.amazon.com/corretto/
- BellSoft Liberica: https://bell-sw.com/
- Azul (Zulu / Azul Platform): https://www.azul.com/
- ツール参考: jdeps(JDK 付属)、jlink、jcmd、JFR ドキュメント(OpenJDK)
まとめ
Java 17(JDK 17)は LTS であり、企業運用の基盤更新候補として妥当です。まずは CI へ JDK 17 のジョブを追加して並列でビルド・テストを回し、jdeps 等で内部 API 依存を早期検出してください。特に JEP 403(内部 API の封止)とネイティブライブラリは高リスク領域です。プレビュー機能は段階的に採用ルールを定め、macOS/AArch64 検証やベンダーのサポート・ライセンス条件を踏まえて移行計画を実行してください。以下が移行の要点です。
- CI での並列検証(現行 JDK と JDK 17)を最優先で実施する。
- jdeps / 静的解析で内部 API 依存を洗い出し、ライブラリ更新か設計変更で対処する。
- プレビュー機能は CI で常時テストし、段階的にステージへ展開する方針を定める。
- macOS/AArch64 は実機による回帰検証を行い、コストに応じた検証手段を選定する。
- ベンダーごとのサポート期間・商用サポートを確認し、配布や運用ポリシーを明確にする。