BLOG
技術分解 010|Java 27:ソースコードで読み解く3つの新機能——64ビットオブジェクトヘッダー、プリミティブ型パターンマッチング、構造化並行性
2026年9月15日、JDK 27 が正式リリースされました(GA、build 35)。9つの JEP がもたらされています。多くの報道はプレスリリースのレベルにとどまっています。番号ひとつ、要約ひと言、サンプルコードひと段落という程度です。この記事は別のアプローチを取ります——ソースコードを直接貼るのです。今回のリリースには、それぞれ異なるレイヤーに立つ3つの機能があります。JEP 534 コンパクトオブジェクトヘッダー(HotSpot ランタイム)は、64 ビットアーキテクチャ上のオブジェクトヘッダーを 96 ビットから 64 ビットへ圧縮します。JEP 532 プリミティブ型パターンマッチング(javac)は、instanceof と switch ですべてのプリミティブ型を扱えるようにします。JEP 533 構造化並行性(java.base API)は、関連する一連のスレッドタスクをクローズ可能なスコープにまとめます。本記事では6つのことを分解します。それは何か、コアメカニズムをソースコードの行番号まで掘り下げた解説、技術評価、追いかける価値があるかどうか、有効化の方法、そしてソースコードを読むところから OpenJDK へパッチを提出するまでの道のりです。
一、これは何か
まずは全体像をはっきりさせておこう。JDK 27 には合計 9 つの JEP があり、公式プロジェクトページで確認すると:JEP 523 G1 全環境デフォルト、JEP 527 TLS 1.3 ポスト量子ハイブリッド鍵交換、JEP 531 Lazy Constants(第 3 回プレビュー)、JEP 532 プリミティブ型パターンマッチング(第 5 回プレビュー、本稿の焦点)、JEP 533 構造化並行性(第 7 回プレビュー、本稿の焦点)、JEP 534 コンパクトオブジェクトヘッダーのデフォルト有効化(正式機能、本稿の焦点)、JEP 536 JFR プロセス内データリダクション、JEP 537 Vector API(第 12 回インキュベーション)、JEP 538 PEM エンコーディング(第 3 回プレビュー)。番号が連続していないことに注意。524–530、535 は存在しない。
フォーカスする 3 つの機能は、それぞれが異なるレイヤーを担い、成熟度には大きな開きがある。JEP 534 は正式機能であり、JDK 27 でデフォルト有効化される。変更するのは HotSpot のオブジェクトメモリレイアウトで、Java コードからは完全に透過的だ。沿革:JEP 450(JDK 24)で実験的に導入、JEP 519(JDK 25)で正式機能化したものの非デフォルト、JEP 534(JDK 27)でデフォルト有効化。Owner は Roman Kennke。JEP 532 は言語層のプレビュー機能で、--enable-preview が必要。20 年以上にわたって積もり積もった厄介事を解決するものだ:パターンマッチング、instanceof、switch は長らく参照型しか受け付けてこなかった。JEP 533 は API 層のプレビュー機能で、同様に --enable-preview が必要。「関連する一連のタスク」を、スレッドプールの自由な状態から明確な境界を持つ作業単位へと編成し直す。Authors は Alan Bateman、Viktor Klang、Ron Pressler。JEP 428(JDK 19 でインキュベート)から今日まで一貫して取り組んできた。
三者を貫く一本の糸はこれだ:メモリの節約、コンパイラの負担軽減、並行処理の管理しやすさ、そのすべてがエンジニアリング主義——新しいパラダイムはなく、ひたすら過去の借金を返しているだけだ。
二、コアメカニズム
引用ルールを先に説明しておきます。「JEP の記載」は openjdk.org の公式 JEP ページに基づく情報で、「ソースコードで確認した内容」は openjdk/jdk リポジトリのタグ jdk-27+35 におけるソース原文を、ファイルパスと行番号付きで示したものです。
2.1 JEP 534:96 bits を 64 bits へ圧縮、markWord.hpp のビットマップがすべての答え
64 ビットアーキテクチャでは、従来のオブジェクトヘッダーは mark word(64 bit)に class word(compressed class pointers 有効時は 32 bit)を加えた合計 96 bits でした。JEP 450 の発想は、この 2 つの区切りを廃止し、圧縮後のクラスポインターを mark word に押し込むというものです。公式のレイアウト図(JEP 450 原文より):
Header (compact):
64 42 11 7 3 0
[CCCCCCCCCCCCCCCCCCCCCCHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHVVVVAAAASTT]
(Compressed Class Pointer) (Hash Code) /(GC Age)^(Tag)
(Valhalla-reserved bits)(Self Forwarded Tag)
クラスポインターはさらに 22 bits まで圧縮され、hash code のサイズは不変、Project Valhalla 向けに 4 bits が予約されます。ここまでが JEP の記載に基づく内容で、この後はソースコードとビット単位で照合していきます。markWord.hpp L43–49 の冒頭コメントにあるビットレイアウト図:
// 64 bits (without compact headers):
// unused:22 hash:31 valhalla:4 age:4 self-fwd:1 lock:2
// 64 bits (with compact headers):
// klass:22 hash:31 valhalla:4 age:4 self-fwd:1 lock:2
一言でまとめると:以前は最上位 22 ビットが unused だった場所に、今は klass が入っています。残り 5 つのビットフィールドは一切変わらず、合計はちょうど 64 ビットです。定数定義(同ファイル L116–154、要点となる行を抜粋):
static const int lock_bits = 2;
static const int self_fwd_bits = 1;
static const int age_bits = 4;
static const int hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits;
// Used only with compact headers: the (narrow) Klass* lives in bits 43 to 64.
static constexpr int klass_bits = 22;
細かいポイントは 3 つあります。まず hash は明示的に 31 ビットで cap されており、JEP 450 の「hash code のサイズは不変」と一致しています。次に、22 ビットの narrow Klass は bit 43–64 に存在します。そしてビットフィールドは下位から上位へ lock(2)→self-fwd(1)→age(4)→valhalla 予約(4)→hash(31)→klass(22) の順に並んでおり、コメント・定数・合計の 3 か所が互いに整合しています。スイッチ面では(globals.hpp L131–132):
product(bool, UseCompactObjectHeaders, true,
"Use compact 64-bit object headers in 64-bit VM")
LP64 プラットフォーム向けの正式なプロダクトフラグで、デフォルトは true。歴史と対比すると:JEP 450 の時代には experimental フラグであり -XX:+UnlockExperimentalVMOptions が必要だったが、JDK 27 ではごく普通の product flag の1行になっている。同ファイルの L150 には、32 ビット VM では常に false であることが明記されている。旧レイアウトへ戻したい場合は -XX:-UseCompactObjectHeaders を使う。旧 96 ビットレイアウトは本バージョンでも引き続き維持されており、JEP 534 では旧レイアウトの削除が明確に非目標(non-goal)とされている。記述の根拠と範囲:ロック操作が mark word を上書きしなくなったこと、GC 転送に self-forwarded tag が新設されたことといった機構の説明は JEP 450 のドキュメントに基づくものであり、self_fwd_bits についてはコメントのレベルで裏付けが取れている。ObjectMonitor および GC 転送の具体的な C++ コードは本稿の範囲外のため、ここでは展開しない。
2.2 JEP 532:プリミティブ型のパターンマッチング ― javac は lowering フェーズで何をしたのか
3つの歴史的制限(JEP の記述による):switch のパターンマッチングはプリミティブ型パターンをサポートしない。record パターンのプリミティブ型コンポーネントは厳密に同型でなければならず(JsonNumber(double a) に対して JsonNumber(int age) とは書けない)、一方で言語のその他の場所では自動 widening が働く。instanceof は参照型にしか対応していない。JEP 532 はこれらを一気に解禁し、switch のセレクタを long/float/double/boolean まで拡張した。セマンティクスの核心は exactness——変換で情報が失われなければ exact であり、long→int、int→float が exact かどうかは実行時の入力値に依存するため、実行時のテストが必要になる。unconditionally exact であれば、コンパイル時に決して情報が失われないと断定できる(type-based と value-based の2種類)。dominance・exhaustiveness の規則もこれに伴って拡張され、浮動小数点の case 定数は表現上の等価性で重複判定される。公式サンプル(JEP 532 の原文):
switch (x.getStatus()) {
case 0 -> "okay";
case 1 -> "warning";
case 2 -> "error";
case int i -> "unknown status: " + i; // 原 default 分支
}
int i = 1000;
if (i instanceof byte b) { ... } // false,不进入分支
float f = 1000.0f;
f instanceof int; // true (exact)
ソースコードで確認できたこと(TransPatterns.java)。instanceof のプリミティブ型テストは lowering フェーズで書き換えられている。L200–221:
// $expr instanceof $primitiveType
// =>
// $expr instanceof T $temp && $temp instanceof $primitiveType
if (tree.erasedExprOriginalType!=null && ...) {
BindingSymbol temp = new BindingSymbol(Flags.FINAL | Flags.SYNTHETIC, ...);
// 先对擦除前类型做绑定模式匹配,再对临时变量做原始类型测试
result = translate(resultExpr); // 两段式 && 复合表达式
}
expr instanceof int という一文は、プリミティブ型テストのバイトコードを直接生成するわけではなく、二段階の AND 演算になります。まず値を合成された FINAL | SYNTHETIC の一時変数に収め(名前に syntheticNameChar が含まれ、ユーザー変数と衝突しない)、次に「この変換で情報が失われたかどうか」を問います。第一段階は値を安全に持ち帰る役割を担い、第二段階は実行時の exactness 判定です。L772–828 の makePrimitive がもう半分の答えを示しています。プリミティブ型は ConstantBootstraps.primitiveClass という定数ブートストラップメソッド(condy)を経由して Class オブジェクトを取得し、シグネチャは PrimitiveGenerator が組み立てます――つまりコンパイラは、プリミティブ型パターンのために invokedynamic と定数プールの素材を生成しているのです。さらに L510 では、セレクタがプリミティブ型の場合は null チェックが免除され(プリミティブ型に null は存在しない)、L935 のバインディングパターンの null チェックは、型がプリミティブかどうかで 2 つの分岐に分かれています。記述範囲の境界:exactness、dominance、exhaustiveness の完全なルールは JEP ドキュメントからのみ取得したものであり、Attr.java、Check.java 内のコンパイル時実装は本稿の範囲外です。
2.3 JEP 533:構造化された並行性――1 つの sealed インターフェースと 1 台の三状態ステートマシン
構造化された並行性は、関連する一群のタスクを 1 つの作業単位として扱います。サブタスクはデフォルトで仮想スレッド上で動作し、fork/join/close を呼び出せるのは owner スレッドのみで、違反すれば StructureViolationException がスローされます。1 つのサブタスクが失敗すると即座にショートサーキットして残りをキャンセルし、owner が割り込まれるとスコープを閉じて全サブタスクをキャンセルします。サブタスクは ScopedValue を継承し、JSON thread dump はタスクの階層ツリーを表示します(以上の実行時動作はいずれも JEP の記述に基づくものです)。本バージョンの 5 つの変更点(JEP 533 History):インターフェースと Joiner に第 3 の型パラメータ R_X(join() がスローする例外の型)を追加。新たに open(UnaryOperator) を追加。allSuccessfulOrThrow() など 3 つのファクトリメソッドは join() が ExecutionException をスローするようにし、それぞれ Function を取るオーバーロードを追加。Joiner.awaitAll() を削除。onTimeout() は timeout() に置き換えられ、タイムアウト例外は CancelledByTimeoutException を cause とします。公式サンプル(JEP 533 原文より):
try (var scope = StructuredTaskScope.open()) {
Subtask<String> user = scope.fork(() -> findUser());
Subtask<Integer> order = scope.fork(() -> fetchOrder());
scope.join();
return new Response(user.get(), order.get());
}
ソースコードに見る実態(StructuredTaskScope.java、全ファイル 1469 行、実装クラス StructuredTaskScopeImpl)。L373–421:
public sealed interface StructuredTaskScope<T, R, R_X extends Throwable>
extends AutoCloseable
permits StructuredTaskScopeImpl {
sealed interface Subtask<T> extends Supplier<T> permits StructuredTaskScopeImpl.SubtaskImpl {
enum State { UNAVAILABLE, SUCCESS, FAILED }
2 つの sealed が構造を釘付けにしている:scope はパッケージプライベートの実装クラスのみを permit し、Subtask は SubtaskImpl のみを permit する。インキュベート期間、この API は jdk.incubator.concurrent にあり、JDK 27 での正式な居場所は java.base の java.util.concurrent だ――インキュベータ卒業からプレビューへ、モジュールの帰属が進化の道標となる。Subtask の状態マシンは 3 状態のみで、かつ extends Supplier<T> なので、get() がそのまま結果を取り出す。Future のあの雑多な面構えは一切ない。Joiner のデフォルトメソッド(L572–618)は状態の規律をコードに書き込んでいる:onFork はサブタスクが必ず UNAVAILABLE であることを要求し、onComplete は UNAVAILABLE のままであってはならないことを要求する。この 2 つのアサーションが、コールバックの中で何が見えるかを完全に固定している。open ファクトリの 3 層デフォルト(L1268–1269):引数なしの open() は Joiner.awaitAllSuccessfulOrThrow() を通る――どれか 1 つでもサブタスクが失敗すれば全体が失敗となり、javadoc(L1173–1176)には、デフォルト設定では名前なしの仮想スレッドを生成し、タイムアウトはなしと明記されている。ファイル全体の公開 API にはすべて @PreviewFeature(STRUCTURED_CONCURRENCY) が付いている――ソースコードレベルで改めて確認できるのは、これがまだプレビュー API だということだ。扱う範囲の境界:仮想スレッドの生成ポイント、キャンセル伝播における割り込み呼び出し、timeout のタイマー機構はいずれも実装クラスの中にあり、本稿ではその内部コードを参照しない。
三、技術評価
まずエビデンスの形をはっきりさせておく:ソースコードの引用はすべて jdk-27+35 タグから。パフォーマンス数値はすべて JEP 公式ページからの引用であり、公式発表の数字であって、独立した再計測ではない。
JEP 534:メカニズムは立証可能、利得は公式を信頼。 メカニズムの面では、ビットレイアウトのコメント、ビットフィールド定数、デフォルトフラグの 3 か所のソースコードが互いに噛み合っており、圧縮スキームがコードの中で完全に自己整合している。これがハードな証拠だ。利得の面では、公式が引用する数値として:あるシナリオでは SPECjbb2015 のヒープ使用量が 22% 減、CPU 時間が 8% 減。別のシナリオでは GC 発生回数が 15% 減(G1 でも Parallel でも同様)。高並列の JSON パース・ベンチマークでは 10% 高速化。裏付けもまた JEP 自身の記述による:Amazon では数百の本番サービスで使用中(多くは JDK 21/17 に backport 済み)、SAP の SapMachine ではすでにデフォルトで有効化されている。リスクも明記されている:Valhalla のために 4 bits を予約しており、足りなければクラスポインタと identity hash code をさらに圧縮できる(JEP 450 の方針による)。冷水を浴びせるなら:klass_bits は 22 にハードコードされており、クラス空間のアドレッシング上限はさらに狭められた——ビット幅と引き換えにデフォルト有効化を得る、明確なトレードオフである。
JEP 532:セマンティクスは安定、それでもプレビューのまま。 5 回目のプレビューであり、しかも今回は JDK 26(JEP 530)から変更なしのまま再プレビューされている——これはセマンティクスがほぼ収束したことを示すシグナルだ。しかし「5 回目」という事実そのものが、まだ正式機能になっていないことを物語る。構文にはまだ調整の余地があり、本番での大規模展開には手戻りリスクがある。実装の面では、2 段階の lowering に加え condy で Class を取得するという点から、コンパイラ内部での扱いが軽くないことが分かる——プリミティブ型をパターンマッチに組み込む代償として、javac が中間構造をもう 1 層生成するのである。
JEP 533:API サーフェスは収束に向かっている。 7 回のプレビューの中で最も頻繁に変更されてきた部分——構築方法、完了戦略、タイムアウト機構——は、JDK 27 で R_X に open(UnaryOperator)、さらに timeout() を加えた 3 つのアクションに収まった。典型的な収束期の姿だ。sealed インターフェースで実装を絞り込み、ステートマシンを 3 状態に切り詰めた——設計の抑制ぶりが見て取れる。冷水を浴びせるなら:7 回目のプレビューであることは、恒久的な互換性をまだ約束していないことを意味する。キャンセル伝播とタイムアウトの内部機構は実装クラスの中にあるため、評価はインターフェースのセマンティクスの層で止めざるを得ない。
全体を見ると。 成熟度の階段は明確だ:534 はアップグレードすればすぐに使える。532 と 533 はプレビューフラグを有効にする必要があり、いずれも長期の安定性が求められるクリティカルパスに入れるべきではない。三者とも新しい概念を導入しない——コンパクトヘッダーはビットの再利用であり、プリミティブ型パターンマッチは widening をパターンに補ったもの、構造化並行性は構造化の原則を並行処理へ持ち込んだものだ——エンジニアリング主義のもう一面:驚きはなく、魔法もない。
四、価値判断
本物の問題はどれも本物だ:オブジェクトヘッダーのオーバーヘッドは 64 ビットヒープ上で長年批判されてきた。instanceof と switch がプリミティブ型を排斥しているのは言語の一貫性における古い傷であり、並行コードにおけるエラー処理とキャンセル伝播は、Java プログラマーの事故率が最も高い領域のひとつだ。3 つの JEP はそれぞれ、本物の問題を一つずつ狙い撃ちにしている。
AI がコードを書く量はますます増えているのに、人間がソースを読む価値はむしろ上がっている。軽くひとこと添えると:大量のコードがモデルによって生成されたあと、人間が浮いた時間をどこに使うか——費用対効果のきわめて高い行き先は、もう一段深く読み下すことだ。コンパイラが新しい構文をどんなバイトコードに変換するのか、ランタイムがオブジェクトヘッダーのどのビットに手を入れたのかを見る。コンパイラとランタイムは、読んでいないからといって簡単になってくれるわけではない。言語機能が増えるほど、「ソースの中で実際に何が起きているか」と「自分が書いたコード」との距離は遠くなる。expr instanceof int がバインディングパターンと AND 演算による二段階の形に書き換えられるのは、まさにその例だ:構文糖衣だけを見れば一回のテストに見えるが、TransPatterns を読んで初めて、それが一回の型の回収と一回の実行時 exactness 判定であると分かる。
メモリの節約は AI サービスのデプロイに直接的な意味を持つが、誇張は禁物だ:JVM 上の推論サービス、検索サービス、Agent ゲートウェイでは、ヒープ使用量が一段下がるたびにクラウドの請求額も一段安くなる。オブジェクトヘッダーを 3 分の 1 削るのは、オブジェクト密度の高いサービスにとって確実に追い風となる方向だ。ただし「方向」は「自分のサービスがまさにその 22% だ」ということを意味しない。得られる利益はオブジェクトのサイズ分布とアロケーションレート次第だ。
境界線ははっきりさせておく:532、533 はプレビューであり、JDK 28 でさらに調整されたり、再びプレビューになったりする可能性もあるため、本番コードでは正式化を待つこと。534 はデフォルトで有効だが元に戻せるので、監視ツールやネイティブエージェントとの互換性問題が出たときも、ロールバック用のキーは残っている。本稿の性能と裏付け情報はいずれも公式の口径に基づくものであり、引用の際は同じ口径を保つこと。いつ追いかけるべきか:JVM サービスを保守し、メモリの請求額を気にし、並行処理の激しいコードを書いている人は、今すぐ --enable-preview を付けて 532、533 を使い込んでおこう。いつ追いかけるべきでないか:API の恒久的な安定性が求められる重要な本番パスでは、正式化を待つこと。
五、どうやって現場に落とし込むか
スイッチ。 JDK 27 はすでに GA(2026-09-15、build 35)。JEP 534 はデフォルトで有効になっており、追加パラメータは不要。LP64 では有効、32 ビットでは常に無効。-XX:+PrintFlagsFinal で UseCompactObjectHeaders を確認すれば、true になっているはずだ。JEP 532 と 533 はプレビューであり、コンパイルと実行の両側で --enable-preview が必要(javac には --release 27 を追加)。どちらか片方でも欠けると即座に拒否される。
サンプルを動かす。 2.2 節・2.3 節の公式サンプルが最小の入り口だ。2 つのバリエーションを試すのがお勧め:case int i を case long i に変えて dominance エラーを出してみる。Joiner.anySuccessfulOrThrow() をデフォルトの open() に変えて、失敗伝播の違いを確かめる。ルールを十回読むより、一度自分の手で試すほうが勝る。
ソースを読む。 経路は 2 つある。インストール済みの JDK には lib/src.zip が同梱されており、展開すれば java.base と jdk.compiler のソースが手に入る。HotSpot の C++ は GitHub の openjdk/jdk に当たることになる。tag jdk-27+35 を checkout し、次の 4 つのファイルを直接参照しよう:src/hotspot/share/oops/markWord.hpp(L40–76 のコメント、L116–154 の定数)、src/hotspot/share/runtime/globals.hpp(L131 のスイッチ)、src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java(L200–221、L772–828)、src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java(L373–1468)。読み方:まず先頭のコメントと javadoc を読む——OpenJDK のコメント密度は非常に高く、ビットレイアウト図も変換ルールもすべてコメントに書かれている——そのうえで、疑問点を手掛かりに実装へ飛び込む。行単位で根を詰めて読み込む必要はない。
六、自分で同様の仕組みを作るには
このコラムの「自分で再現する」を JDK に置き換えると、最も現実的な道筋は、ソースコードを読むところから始めて、OpenJDK へ小さなパッチを投稿するところまで進むことです。OpenJDK は巨大なプロジェクトですが、個人コントリビュータにとって乗り越えられない高い壁ではありません。四つの段階に分けて説明します。
第一段階は、ソースコードを読んで土台を固めること。 第五節の四つのファイルから着手し、先頭のコメントを十分に読み込んだら、そこから糸をたどっていきます。markWord.hpp からは oops 階層を下って読み、TransPatterns.java からは上流へ向かって TreeTranslator と同じディレクトリの Attr、Check を読み、StructuredTaskScope.java は実装クラスに直結しています。目標はすべてを理解することではなく、「一つのファイルを変更するとどこに影響するか」という感覚を養うことです。
第二段階は、ローカルビルド。 openjdk/jdk にはビルドシステムが付属しており、Unix 系プラットフォームでは ./configure の後に make images を実行します。初回のフルビルドには 1〜2時間かかりますが、その後のインクリメンタルコンパイルは数十秒で済みます。ローカルでビルドできるようになって初めて、実験台を手に入れたことになります。
第三段階は、テストを回してからコードを変更すること。 OpenJDK では jtreg を使います。javac のテストは test/langtools、HotSpot は test/hotspot/jtreg、JDK API は test/jdk にあります。正しい進め方は、まず失敗する新しいテストケースを書き(プレビュー機能では特に境界ケースの追加が歓迎されます)、その後でコードを変更して通るようにすることです。
第四段階は、投稿のプロセス。 常識的な工程としては、スタイルとコミット形式はリポジトリ付属の jcheck に従い、変更は webrev の形式でコンポーネントのレビューリストに掲げて Committer にレビューしてもらいます。初めて貢献する前には OCA(Oracle Contributor Agreement)に署名します。電子署名で、公式のコントリビュータページの記載が正となります。狙いどころの選択としては、532、533 はプレビュー期間中にあり、javadoc の文言、エラーメッセージ、境界テストといった低リスクの改善は、実際的で歓迎される入口です。HotSpot のビットレイアウトとフラグのドキュメントも、同様に年間を通じて小さな修正を受け付けています。具体的な帰属先やメンター制度については、各プロジェクトページの現在の説明を基準にしてください。
これを一枚の図に圧縮すると:
读源码(markWord.hpp / TransPatterns.java / StructuredTaskScope.java)
→ ./configure && make images(本地构建 JDK 27 镜像)
→ jtreg 跑目标组件测试(test/langtools、test/jdk……)
→ 先写失败用例,再改实现,再跑绿
→ jcheck → webrev 挂评审 → OCA(首次)→ Committer 合并
難易度の分布は正直なところ、最初の二段階は経験者なら二週間以内に完了でき、第三段階からはコンポーネントへの理解が試され、第四段階のレビューの往復が最も長くかかります。それでもメリットは他にはないものです。あなたが変更した一行一行が、来年には世界中の数億の JVM 上で動くのですから。
結論
JDK 27 の 3 つの特性は、同じコインの 3 つの面です。JEP 534 はオブジェクトヘッダーを 96 bits から 64 bits へ圧縮します。markWord.hpp のビットマップと globals.hpp のデフォルトフラグは、これが成熟したエンジニアリングであることを証明しており、得られる恩恵は公式の見解を基準とします。JEP 532 は instanceof と switch ですべてのプリミティブ型をサポートできるようにし、TransPatterns の 2 段階式の降訳により実行時の exactness 判定が実現されました。変更なしで 5 回目の再プレビューとなったことは、セマンティクスが収束したことを意味します。JEP 533 は構造化並行性を java.base に取り込み、sealed インターフェース、3 状態のステートマシン、awaitAllSuccessfulOrThrow のデフォルトポリシーはソースコードを見れば一目瞭然です。3 つとも新しいパラダイムではなく、いずれも溜まっていた旧債の返済です。アップグレードすれば 534 はそのまま得られ、残りの 2 つは --enable-preview を付けて使い込んで慣れておき、正式化されてから本番環境へ載せればよいでしょう。
参考出典
- JEP 534: Compact Object Headers by Default(openjdk.org/jeps/534;Owner: Roman Kennke;Closed/Delivered, Release 27)
- JEP 450: Compact Object Headers (Experimental)(openjdk.org/jeps/450;コンパクトレイアウトのビットマップと圧縮メカニズムの詳細)
- JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview)(openjdk.org/jeps/532;Owner: Angelos Bimpoudis;ルール体系と公式サンプル)
- JEP 533: Structured Concurrency (Seventh Preview)(openjdk.org/jeps/533;Authors: Alan Bateman, Viktor Klang, Ron Pressler;API の形式、5 つの変更点と公式サンプル)
- openjdk/jdk ソースコード(GitHub、tag jdk-27+35):markWord.hpp(L40–76、L116–154)、globals.hpp(L131–132、L150)、TransPatterns.java(L200–221、L510、L772–828、L935)、StructuredTaskScope.java(L373–1468)
- JDK 27 プロジェクトページの JEP 一覧(openjdk.org/projects/jdk/27、「JDK 27 reached General Availability on 15 September 2026」)