- Growing the Language
- Marshaling
- Symbolic modeling of Java Code
- Evolving closure with virtual threads
- Off-CPU Profiling in Java
- Evolving ZGC
Growing the Language (Brian Goetz)
概要
Brian Goetz は、言語設計の拡張性について語り、ユーザーが追加する抽象化が組み込みの言語機能に似ていることの重要性を強調した。Java における Farish ループ や private resources 構文を、拡張可能な言語機能の例として紹介した。
Goetz は、type classと witnessを用いることで、暗黙の型変換や演算子オーバーロードなど、より柔軟で拡張可能な言語機能を実現できると提案した。また、他の JVM 言語との相互運用性や静的型チェックの課題にも触れ、Java のシンプルさを損なわずに表現力を高めることを目指している。
今後の計画
- type classの概念をさらに調査し、Java の言語機能拡張にどう応用できるか検討する。
- Scala や Kotlin など他の JVM 言語が拡張性やレトロアクティブモデリングにどう対応しているか調査する。
- type classの導入が Java の型システムの理解に与える影響と、将来の言語機能への可能性を評価する。
- 暗黙の型変換の利点と混乱の可能性のバランスを慎重に検討する。
- Java のプログラミングスタイルを「継承」から「合成」へとシフトさせる可能性を議論し、既存 API の見直しを検討する。
内容の構成
言語設計と拡張性
- ユーザーが言語の語彙を拡張できる設計の重要性を強調。
- Project Calpalus の出発点として Guy による論文を紹介。
- Java の過去の例(Farish ループ、private resources)を通じて「成長可能性(growability)」の概念を説明。
拡張可能な言語機能の例
- Farish ループ:
Java.Lang.Intervalを使って、ユーザー定義クラスが組み込み機能のように振る舞える。 - private resources:Java 7 の機能で、ブロック内で取得したリソースを自動的にクローズする。
課題と教訓
- 拡張を見越した設計の重要性。
- 閉じた機能よりも設計が難しいが、リターンが大きい。
- Project Valhalla のような数値型の拡張が動機の一つ。
Project Valhalla と数値型
- プリミティブに近い動作を持つ数値クラスの実現。
- 型変換や演算子オーバーロードの課題。
- インターフェースの限界と新たなメカニズムの必要性。
type classとwitness
- Haskell に似た「type class」の導入。
- type classは型の振る舞いを定義するインターフェース。
- witnessはそのインターフェースのインスタンス。
- witnessの導出、公開、検索の仕組みが必要。
実装と制約
- フィールドやメソッドにwitnessマークを付けて公開。
- witnessはsymbolic constantである必要がある(最適化のため)。
- 実行時のwitness検索とtype erasureとの関係。
質疑応答と今後の方向性
- JVM 他言語との相互運用性。
- type classによるパラダイムシフト。
- witnessの実行時解決とラムダ式との類似性。
- 暗黙の変換によるバグの懸念と制限。
- 既存クラスのwitness対応の可能性。
- インターフェース使用の制限とsymbolic constantの利点。
Marshaling (Viktor, Stuartが代理で説明)
概要
Stuart Marksは、病欠の Viktorの代役として登壇し、「Serialization 2.0」とも呼ばれる新しいマーシャリング設計について発表した。これは、従来の Java のシリアライズ(Serialization 1.0)の課題を克服し、より安全で柔軟なデータ変換を実現するための進化版である。
Serialization 1.0 の課題
- 脆弱なエンコーディング:バイナリ形式が壊れやすく、デバッグが困難。
- 型安全性の欠如:静的型チェックがなく、セキュリティリスクが高い。
- magicメソッドやフィールドに依存し、コードの理解と保守が困難。
- 言語機能をバイパスしてオブジェクトを復元するため、カプセル化や整合性が損なわれる。
Serialization 2.0(Marshaling)の設計思想
- 言語機構を活用:魔法のようなコードを排除し、通常の JVM オブジェクトと構文で制御。
- クラス作成者が制御:オブジェクトの状態をどのように外部表現するかを定義可能。
- ストリーミング方式:メモリの重複を避けるため、データを逐次処理。
- スキーマベース:データの型や構造を記述するスキーマを導入。
- アノテーションとメソッドハンドルを使ってマーシャリング/アンマーシャリングを制御。
- 副作用のないデシリアライズを保証し、セキュリティを強化。
実装例とパターン
- HashMap のカスタムマーシャリング例では、キーと値のペアを順に書き出す。
- Point クラスの手動マーシャリングでは、データを抽出して出力ストリームに書き込む。
- deconstruction patternsを使って、recordのように通常のクラスも扱える。
- 複数のマーシャリング方式をサポート可能。
セキュリティとバージョン管理
- スキーマを信頼し、ワイヤフォーマット(バイナリ形式)には依存しない。
- バージョン管理が重要課題:複数バージョンのサポートや適応的なデシリアライズが必要。
- 循環参照やオブジェクトの同一性保持はサポートせず、シンプルで安全な設計を優先。
今後の計画
- メモリ内オブジェクトとワイヤフォーマット間の変換に使うスキーマ設計の確定。
- インターフェース型やジェネリック型の扱い方の検討。
- セキュリティリスクとその緩和策の調査。
- バージョン管理と複数フォーマット対応の方針決定。
Symbolic modeling of Java Code (Paul Sandoz)
このセッションでは、Javaコードのリフレクション(コード自身を扱う機能)と機械学習との統合に向けたコードモデルの開発について議論された。
セクション1:コードリフレクションと静的・動的解析
- Javaコードを「操作(operations)」「本体(bodies)」「ブロック(blocks)」の3要素からなるツリー構造としてモデル化。
- 静的解析(コード構造の把握)と動的解析(実行時の振る舞い)を組み合わせたアプローチを強調。
- コードの99%がインキュベーター(試験導入環境)にあり、実験とフィードバックを重視。
- if文や条件式の統一的な処理、ループ、パターンマッチングなどの複雑な構造もモデル化可能。
- load, store, add, return などの操作を含む明示的な型変換もサポート。
- Point クラスなどを例に、手動マーシャリング(データの分解と再構築)を紹介。
セクション2:Onixライブラリと機械学習統合
- Onnxライブラリは、OpenNeuroのニューラルネットワークをJavaから操作するための物理モデル。
- Java APIを通じて、テンソル演算やstaticメソッドを使ってOnnxモデルを構築可能。
- protobuf形式でモデルを表現し、Jextractを使ってネイティブライブラリで実行。
- デモでは、2つのモデルを同時に実行し、コンテキストサイズを変更してモデルの挙動を変化させることに成功。
- JavaコードからOnnxモデルを動的に操作・実行できる可能性を示した。
今後の計画
- コードリフレクション機能をインキュベーションに向けて準備。
- if文と条件式の処理統一方法を検討。
- コードモデルの例を詳しく解説するワークショップを開催。
- Onnxライブラリとコードリフレクションモデルの統合。
Evolving closure with virtual threads (Alex Miller)
Alex Millerは、Clojure の進化について、特に以下の3点に焦点を当てて解説した。
- Core Async ライブラリ
- 仮想スレッド(Virtual Threads)
- 新ライブラリ Flow
Clojure の特徴と背景
- Clojure は 2007 年に Rich Hickey によって開発された 関数型プログラミング言語。
- JVM 上で動作し、不変コレクションと ソフトウェアトランザクショナルメモリ(STM) による状態管理を特徴とする。
- Nubank(南米最大のフィンテック企業)では、Clojure を広範に使用しており、基幹データベースも Clojure 製。
Core Async と仮想スレッド
- Core Async(2013年リリース) は、非同期通信のためのチャネルを提供。
- go ブロックは、仮想スレッドのようにスレッドから切り離されて実行可能。
- JVM の 仮想スレッド により、ブロッキング IO やプロセス調整が効率化。
- Core Async は、IO・計算・混合ワークロード向けに仮想スレッドベースのエグゼキュータープールを導入。
Flow ライブラリの登場
- Flow は、アプリケーションロジックとプロセステクノロジーを分離する新ライブラリ。
- プロセス、接続、フロー という概念を導入し、チャネルを通じて通信する 有向グラフ を構築。
- 各プロセスは、状態管理・エラーハンドリング・テスト可能な純粋関数を担当。
- Flow の設定ファイルで、プロセス・接続・エグゼキューターを定義し、起動・接続・ライフサイクルを管理。
ディスカッションと今後の課題
- マルチアリティ関数 vs プロトコル:Flow ではプロトコルよりもマルチアリティ関数を選択。値を単位として渡す柔軟性が理由。
- 仮想スレッドとの関係:Flow の設計は仮想スレッドに影響を受けたが、独立して開発されており、仮想スレッドなしでも実装可能だった。
今後の計画
- Flow ライブラリでプロトコルではなくマルチアリティ関数を使う理由を講演者に確認。
- Flow の構想と Java の仮想スレッドの関係性を調査。
Off-CPU Profiling in Java (Lin)
- 発表者は Alibaba Cloud JVM チームのメンバーで、緊急診断と Java アプリケーションのパフォーマンス問題に注力。
- JDK 11 から JDK 21+ への移行により、レイテンシーが約10%、Young GC 時間が25〜30%削減されたと報告。
- チームは Hangzhou と Shanghai を拠点に、クロスアーキテクチャ性能、Spark/Flink 向け分散処理、JDK アップグレード、プロファイリングツールなどを研究。
Java ディストリビューションと新機能の採用
- Alibaba は 2 種類の Java ディストリビューションを保有:
- Second Well(オープンソース)
- AJDK(社内用)
- AJDK は Alibaba の E コマースアプリケーションで広く使用されており、中国最大級の Java デプロイメント。
- OpenJDK の Loom や Lilliput などの最新機能を積極的に採用・検証。
レイテンシー診断の課題と手法
- レイテンシー問題の主因として CPU(スケジューリング、ネットワーク)を特定。
- Spark や Flink のような計算・I/O 混在型ワークロードの最適化において、CPU 使用率と I/O 待機時間の可視化が重要。
- GC によるレイテンシーは JDK 21 で大幅に改善されたが、今後は I/O やスケジューリングの最適化が鍵。
ケーススタディ:Spark と IO ボトルネック
- DPCDS ベンチマークのクエリ 28 は I/O バウンドで、JVM がスループットを優先しすぎてキャッシュ領域が圧迫される問題を観測。
- 解決策:JVM に I/O 待機時間を認識させ、ヒープサイズを動的に縮小 → I/O 使用率が向上し、レイテンシーが 52 秒 → 35 秒に短縮。
フルスタック診断と Akira ツール
- 異なるハードウェア間での性能比較には、スレッド間の依存関係やスケジューリングの可視化が必要。
- 既存のプロファイラでは Java シンボルの取得やトランザクション単位の分析が困難。
- Akira ツールの紹介:
- トランザクションの開始・終了を指定し、スレッドのスケジューリング、待機、CPU 使用時間を可視化。
- トランザクションの依存関係グラフを生成し、ボトルネックを特定。
- 仮想スレッドにも対応し、スレッド ID が変化してもコンテキスト識別子で追跡可能。
デモと成果
- ScratchDB 上でのパッチ適用後のレイテンシー劣化(900μs → 1500μs)を Akira で分析。
- 長いトランザクションは中間スレッド数が多く、スケジューリングのシャットアウトが頻発。
- 仮想スレッド導入により、スケジューリング時間が 25% → 5%、P50 レイテンシーが 2300μs → 1500μs に改善。
まとめと今後の展望
- Java がよりコストレスになる中で、レイテンシー問題の再評価が必要。
- I/O 意識の重要性と、クラウドプロバイダーとしての診断能力の強化が求められる。
- Akira のようなツールにより、レイテンシーの要因(スケジューリング、I/O)を分解・可視化することが可能。
- 今後の貢献機会として、仮想スレッド最適化や診断ツールの改善が期待される。
Evolving ZGC (Erica Suleman)
Oracle Java Platform Group の Erica Suleman が、ZGC(Z Garbage Collector)におけるカラーポインタの進化について解説した。
カラーポインタとは?
- カラーポインタは、ポインタにメタデータ(色)を埋め込むことで、GC(ガベージコレクション)の状態遷移や並行処理を効率的に管理する技術。
- Persistent Color(永続色):ロード後も残る色で、オブジェクトのプロパティを表現。
- Transient Color(一時色):ロード後に消える色で、主に参照やエッジの状態を表現。
実装と構造
- 64ビットポインタの高位ビットを使って色をエンコード。
- 非世代別ZGCでは、3色(Mark Even, Mark Odd, Remap)を使ってGCサイクルを管理。
- 世代別ZGCでは、12ビットの色を使い、young世代とold世代のGCを区別。
- 色の遷移により、GCアクション(マーキング、リロケーションなど)をトリガー。
メモリ管理と最適化
- RSS(Resident Set Size)膨張問題:マルチマップメモリによる仮想アドレスの重複が原因。
- Colorless Roots:一時色をロード時に除去することで、RSS膨張を回避。
- Heap Partitioning:NUMAノードごとにヒープを分割し、物理メモリの近接性を考慮した割り当てを実現。
- 新しいメモリ管理機構:Heap Region Cache を廃止し、Heap Mapped Cache による断片化の低減。
将来の方向性
- Private vs Shared オブジェクトの分離:スレッドローカルGCの実現に向け、オブジェクトの所有権を明示。
- Persistent + Transient Color の併用:オブジェクトと参照の両方のプロパティを効率的に表現。
- 16個のTransient Color + 1個のPersistent Color への拡張を計画中。
バリアとGCトリガー
- Store Barrier:効率的なストア操作のためのバリア設計。
- Load Barrier:初回アクセス時に色をチェックし、必要に応じてGCアクションを実行。
- Remembered Set:old世代からyoung世代への参照を追跡し、young世代GC時の生存確認に使用。
Q&A ハイライト
- PrivateメモリはEscape Analysisに依存? → GCが検出するまではグローバル扱い。
- スレッド数制限は? → NUMAパーティションごとに管理、制限なし。
- 転送アドレスの保存場所は? → オブジェクト外のオフヒープテーブルに保存。
- 仮想スレッドとプラットフォームスレッドの違いは? → 最適化は仮想スレッドに限定。
- なぜポインタに色を持たせるのか? → オブジェクトではなく参照(エッジ)のプロパティを追跡するため。
今後の計画
- 永続色によるオブジェクトプロパティのエンコードと一時色との併用を検討。
- RSS膨張を回避するためのHeap Partitionと新しいメモリ管理機構を調査。
- Finalizer廃止に伴う色ビットの再利用可能性を検討。