Slide 1

Slide 1 text

GraalVM 最新事情 Oracle Cloud Hangout Cafe - Season 6 #2 Tadahisa Kotegawa Senior Director, Solutions Architect Oracle Corporation Japan October 5th , 2022

Slide 2

Slide 2 text

Copyright © 2022, Oracle and/or its affiliates 2 あれから 3年 経ちました… 2019年9月19日開催 https://ochacafe.connpass.com/event/140792/

Slide 3

Slide 3 text

Copyright © 2022, Oracle and/or its affiliates 3 1. GraalVM のおさらい 2. ネイティブ・イメージ 3. 言語ランタイムとツール 4. まとめ Agenda

Slide 4

Slide 4 text

Copyright © 2022, Oracle and/or its affiliates 4 自己紹介 古手川 忠久 日本オラクル株式会社 ソリューションアーキテクト本部 Oracle Developer Days 2022 Spring 【パネルディスカッション】徹底討論!マイクロサービス開発におけるJavaの最適解 https://developer.oracle.com/jp/developer-days-2022-may/on-demand/#cloudday CodeZine 「日本のマイクロサービスの現在地は? Javaはマイクロサービスに向いているか?」 https://codezine.jp/article/detail/16148 @tkotegaw tkote oracle-japan @tkote

Slide 5

Slide 5 text

PART 1: GraalVMのおさらい Copyright © 2022, Oracle and/or its affiliates 5

Slide 6

Slide 6 text

Copyright © 2022, Oracle and/or its affiliates 6 新たな JIT コンパイラがもらたす 高い Java パフォーマンス • インフラコストの削減 • アプリコードの変更不要 • Javaエコシステムの生産性をそのまま 活用可能 多言語 (Polyglot) プログラミング • 各種言語の高性能ランタイム Node.js, Python, R, Ruby, C/C++, etc. • 複数の言語をひとつのアプリケーション から呼び出せる • 独自の言語実装/実行が可能 AOT コンパイラによる ネイティブ・イメージの作成 • 小さなメモリ・フットプリント • 起動時間の短縮 (ウォームアップなし) • コンテナ・アプリに最適 プロファイル、デバッグ、モニタリングを 支援する先進的なツール群 • VS Code Extensions • Chrome Debugger • VisualVM, etc. GraalVMとは ? 高性能なJDKディストリビューション

Slide 7

Slide 7 text

Copyright © 2022, Oracle and/or its affiliates 7 Javaで記述されたJust-in-Time (JIT) コンパイラ = Javaバイトコードをマシン・コードに変換する • JVMコンパイラ・インタフェース (JVMCI) をサポートする Java HotSpot VM と統合されている JVMで実行されるプログラムのパフォーマンスを最適化 • 高度に抽象化されたプログラムのパフォーマンス向上 - stream, lambda など • 低レベルのコード、I/O、メモリ割当て、ガベージ・コレクションなどの比重が高いコードでは改善効果小 • GraalVM EE には更に高度な最適化が含まれる GraalVM コンパイラ 従来からの Java アプリケーション (JVM上で動作するアプリケーション) もパフォーマンス向上が期待できる C2 JIT コンパイラ: C1 JIT コンパイラが始動後、プロファイリングメトリクスが収集されてから始動する JIT コンパイラで、より最適化されたコードを生成する OS Java SE Java Application HotSpot VM C2 JIT コンパイラ OS GraalVM Java Application HotSpot VM GraalVM JIT コンパイラ 置き換え 2つの実行モード - libgraal (default) - jargraal (-XX:-UseJVMCINativeLibrary)

Slide 8

Slide 8 text

Copyright © 2022, Oracle and/or its affiliates 8 ネイティブ・イメージ = 必要なコードと依存関係のみを含んだネイティブ実行形式のJavaアプリケーション • Substrate VM が含まれる = ガベージコレクタやスレッドスケジューラといった実行時コンポーネントを提供するVM実装 ネイティブ・イメージ・ビルダー (native-image) でネイティブ・イメージを生成 • 通常のJavaアプリケーションを起動するように起動 • META-INF/native-image/ 配下 (サブディレクトリ含) のすべての構成ファイルを自動的に取得 AOT (ahead-of-time) コンパイラ アプリケーションの起動を高速化し、フットプリントを縮小する → Javaアプリのコンテナ化 (マイクロサービス) に適する ネイティブ・イメージ Substrate VM Java Application (構成ファイル) jar jar jar class native-image コマンド 構成オプション MainClass META-INF/native-image/**/* Java ソースコード Maven リポジトリ $JAVA_HOME/bin/native-image <構成オプション> -jar excutable.jar $JAVA_HOME/bin/native-image <構成オプション> -cp fully.qualified.MainClass リフレクションやリソースなどネイティブ・イメージのビルドに必要な構成情報

Slide 9

Slide 9 text

Copyright © 2022, Oracle and/or its affiliates 9 イメージのビルド時に構成情報が必要なもの • Dynamic Class Loading • Reflection • Dynamic Proxy • JNI (Java Native Interface) • Serialization 動作が異なる可能性のある機能 • Signal Handlers • Class Initializers • Finalizers • Threads • Unsafe Memory Access • Debugging and Monitoring サポートされないもの • Invoke Dynamic Bytecode and Method Handles • Security Manager AOT コンパイラの制約 後述するトレース・エージェントを使って構成ファイルの 自動生成が可能 (完全ではないので注意)

Slide 10

Slide 10 text

Copyright © 2022, Oracle and/or its affiliates 10 GraalVM は Truffleフレームワークを使った一般的な言語用の高性能なランタイムを提供 • Java、JavaScriptおよびNode.js、LLVM言語 (C, C++, Rust)、Python、R、Ruby、WebAssembly ポリグロット機能 - 複数のプログラミング言語を単一のアプリケーションに混在できる 言語実装のためのプラットフォーム • 独自の言語実装(インタープリタ)を開発して GraalVM上で実行することが可能 Language Implementation Framework (Truffle) Truffle 言語実装フレームワーク GraalVM JIT Compiler Language Implementation Framework (Truffle) GraalVM LLVM bitcode interpreter Java on Truffle

Slide 11

Slide 11 text

GraalVM JIT Compiler Language Implementation Framework (Truffle) GraalVM LLVM bitcode interpreter Java on Truffle Copyright © 2022, Oracle and/or its affiliates 11 Truffleフレームワークを使ってJavaで記述された Java バイトコード・インタープリタ JavaSE8 および JavaSE11 の実装 GraalVMエコシステムの他の言語(JavaScript、Ruby、Python、R)と同じメモリ空間でデータをやり取り可能 ホスト JavaVM とは別のコンテキストで Java バイトコードを実行 実行中のアプリケーションを再起動することなくコードのリロード (HotSwap) が可能 Java on Truffle

Slide 12

Slide 12 text

Copyright © 2022, Oracle and/or its affiliates 12 • GraalVM EE は Java SE Subscription に含まれる • Oracle Cloud Infrastructure (OCI) の利用者は GraalVM EE を OCI 上で無償利用可能(ライセンスとサポート) GraalVM のエディション https://www.graalvm.org/downloads/ GraalVM 22.2 Community Edition (CE) Enterprise Edition (EE) ライセンス GNU General Public License V2 with the “Classpath” Exception 商用ライセンス -------------------------- Oracle Technology Network (OTN) ライセンス (開発/テスト) ベースJDKs OpenJDK 11.0.16 and 17.0.4 Oracle JDK 8u341, 11.0.16 and 17.0.4 サポート コミュニティ・サポート Oracleによる商用サポート Renaissance Suite (JVMベンチマーク) で 計測した対 OpenJDK スピードアップ 1.04x 1.3x Docker コンテナ・イメージ ✔ ✔ 特許取得の高度なコンパイラ最適化 ✔ ネイティブ・イメージの最適化 - 圧縮されたポインタによる低メモリ使用 - プロファイルガイド最適化による性能向上 - G1ガベージ・コレクションによる低遅延 ✔

Slide 13

Slide 13 text

Copyright © 2022, Oracle and/or its affiliates 13 ビッグデータ、機械学習、関数型プログラミングなど、一般的な最新のJVMワークロードを集約したベンチマーク・キット パフォーマンス・ベンチマーク https://renaissance.dev/

Slide 14

Slide 14 text

Copyright © 2022, Oracle and/or its affiliates 14 Community Edition • 機能リリース (Feature Release) • 3か月毎 (2,5,8,11月)のマイナーリリース • 最新の機能リリースがサポート対象 • 年次リリース (Annual Release Train) • 暦年毎に構成される一連の機能リリース • 21.x, 22.x • 年次リリースには4つの機能リリース(0-3) • 年次リリースの最後の機能リリース(e.g. 21.3)は12か月 間、バグと脆弱性の修正を提供 • クリティカルパッチアップデート(CPU) • Open JDK にもとづく Enterprise Edition • 機能リリース (Feature Release) • 同左 • 年次リリース (Annual Release Train) • 年次リリースの最後の機能リリース(yy.3)は18か月間 (メンテナンスリリース)のバグ修正を受けつける • 長期サポートリリース (LTS) • 安定した本番環境向け • 2年ごと • 最新LTS 21.3、次回予定LTS 23.3 • クリティカルパッチアップデート (CPU) • オラクルのCPUリリースに従う GraalVM のバージョン・ロードマップとサポート・ポリシー 詳しくはこちらを参照 CE: https://www.graalvm.org/release-notes/version-roadmap/ EE: https://docs.oracle.com/en/graalvm/enterprise/22/docs/version-roadmap/ ※ EEの明確なサポート期限(Premier/Extended)は オラクルライフタイムサポートポリシーに記載されています

Slide 15

Slide 15 text

ポリグロット・アプリケーション GraalVM上のホスト言語 (JavaScript/Node.js, R, Ruby, Python, C) から Javaクラスにアクセス GraalVM GraalVM Copyright © 2022, Oracle and/or its affiliates 15 JVMランタイム HotSpot VM 上の JIT コンパ イラーとして GraalVMコンパイ ラーを使用して実行 ネイティブ・イメージ Javaバイトコードをネイティブ実 行可能ファイルまたはネイティブ 共有ライブラリにコンパイルして 実行 Java on Truffle Truffleフレームワーク上に構築 された、JVMバイトコード・イン タプリタの実装を使用して実行 ひとまずまとめ:Java アプリケーションは GraalVM でどう実行できるのか? OS GraalVM Java Application (byte code) Native Image Substrate VM Java Application (AOT) OS HotSpot VM GraalVM JIT Compiler Truffle Java on Truffle OS Java Application HotSpot VM GraalVM JIT Compiler Truffle OS Polyglot Application JS,R,Ruby,Python,LLVM Java Class HotSpot VM GraalVM JIT Compiler

Slide 16

Slide 16 text

Copyright © 2022, Oracle and/or its affiliates 16 デモ:GraalVMによるJavaアプリケーションの実行

Slide 17

Slide 17 text

Copyright © 2022, Oracle and/or its affiliates 17 Java アプリケーションの実行方法あれこれ # GraalVMで実行 – 通常の実行方法 $ java –cp target/demo-1.0.jar com.example.App Hello World! # Graal JIT コンパイラを敢えて無効にして実行する $ java -XX:-UseJVMCICompiler -cp target/demo-1.0.jar com.example.App Hello World! # Java on Truffle (Truffle上のJVMバイトコード・インタプリタ) で実行する $ java -truffle -cp target/demo-1.0.jar com.example.App Hello World! # Java on Truffle は単一のファイルであればソースファイルも実行できる! $ java -truffle src/main/java/com/example/App.java Hello World! # Java on Truffle で異なるJavaのインストール先にある実行モジュール(=jarとライブラリ)を使用して実行する – バージョンが違ってもOK! $ java -truffle --java.JavaHome=/home/opc/opt/jdk-11.0.15.1 -cp target/demo-1.0.jar com.example.App Hello World! # ネイティブ・イメージの作成 (Maven native-maven-plugin を利用) と実行 $ mvn -Pnative package -DskipTests=true $ ./target/demo Hello World! # Javascript コードから Javaクラスにアクセス $JAVA_HOME/bin/js --jvm -e 'Java.type("java.lang.System").out.println("Hello World!")' Hello World!

Slide 18

Slide 18 text

$ $JAVA_HOME/bin/gu GraalVM Component Updater v2.0.0 Usage: gu info [-cClLnprstuvV] print info about a specific component (from a file, a URL or a catalog) gu available [-aClvV] list components available in a catalog gu install [-0CcDfiLMnosruvyxY] install a component package gu list [-clv] list installed components, or components from a catalog gu remove [-0DfMxv] uninstall a component gu upgrade [-cCnLsuxSd] [] [] upgrade to a recent GraalVM or edition gu rebuild-images ... (省略) $ $JAVA_HOME/bin/gu available Downloading: Component catalog from www.graalvm.org ComponentId Version Component name Stability Origin --------------------------------------------------------------------------------------------------------------------------------- espresso 22.1.0 Java on Truffle Supported github.com espresso-llvm 22.1.0 Java on Truffle LLVM Java librSupported github.com llvm-toolchain 22.1.0 LLVM.org toolchain Supported github.com native-image 22.1.0 Native Image Early adopter github.com nodejs 22.1.0 Graal.nodejs Supported github.com python 22.1.0 Graal.Python Experimental github.com R 22.1.0 FastR Experimental github.com ruby 22.1.0 TruffleRuby Experimental github.com wasm 22.1.0 GraalWasm Experimental github.com Copyright © 2022, Oracle and/or its affiliates 18 GraalVM Component Updater GraalVMの言語ランタイムやユーティリティを管理するコマンドライン・ツール 使用の際は確認下さい

Slide 19

Slide 19 text

PART 2: ネイティブ・イメージ Copyright © 2022, Oracle and/or its affiliates 19

Slide 20

Slide 20 text

Copyright © 2022, Oracle and/or its affiliates 20 ネイティブ・イメージ ~ 基礎編

Slide 21

Slide 21 text

Copyright © 2022, Oracle and/or its affiliates 21 通常 Java を起動するのと同様な起動方法 • 非常にたくさんのオプションあり… 構成ファイルの適用・埋込み • META-INF/native-image/ 下(サブディレクトリ含)のすべての構成ファイルを取得してコマンドライン引数を構築 • プロジェクトJARファイルに埋め込むことで構成を適用・配布することができる → JAR間でバッティングしないようにするための慣習: グループID & アーティファクトID で階層化する ネイティブ・イメージ ビルダー META-INF/ └── native-image └── groupID └── artifactID └── native-image.properties, etc. $ native-image [options] class [imagename] [options] $ native-image [options] -jar jarfile [imagename] [options] $ native-image [options] --module [/] [options]

Slide 22

Slide 22 text

Copyright © 2022, Oracle and/or its affiliates 22 クラスの初期化処理はパフォーマンスに大きな影響を及ぼす • アプリケーション起動時の処理量が多い → 起動所要時間が長くなる AOTによる最適化 • イメージのビルド中に特定のクラスを初期化して、実行時の初期化とチェックを不要にする • 初期化されたクラスのすべての静的状態情報がイメージに格納される ネイティブ・イメージ ビルダーはビルド時の初期化を試みる • 初期化のタイミングによって動作が異なる可能性はある(前述) • オプションで個別に制御可能 --initialize-at-build-time=<カンマ区切りのクラス名orパッケージ名> --initialize-at-run-time=<カンマ区切りのクラス名orパッケージ名> ネイティブ・イメージ ビルダー ビルド時におけるクラス初期化の意味

Slide 23

Slide 23 text

Copyright © 2022, Oracle and/or its affiliates 23 JIT AOT • OS が JVM 実行ファイルをロードする • VM がファイルシステムからクラスをロードする • バイトコードが検証される • バイトコードの解釈が開始される • 静的イニシャライザの実行 • 第1層コンパイル (C1) • プロファイリングメトリクスの収集 • ... (しばらくの後) • 第2層コンパイル (C2/Graal コンパイラ) • 最適化されたマシンコードによる実行 • OS が実行ファイルと設定済ヒープをロードする • 最適化されたマシンコードでアプリケーションが起動する JIT と AOT の起動プロセスの違い ネイティブ・イメージの起動所要時間が短いワケ 出典: Javaに革命を起こすGraalVM Native Image https://www.infoq.com/jp/articles/native-java-graalvm/ 起動プロセスが短いのは分かったけど 静的解析によるコード生成だと プロファイリングによる最適化がされないので 起動後のパフォーマンスはJITコンパイラに 分がありそうな気もする…

Slide 24

Slide 24 text

Copyright © 2022, Oracle and/or its affiliates 24 プロファイリング・データを事前に収集し、ネイティブ・イメージ ビルダーにフィードすることによって、ネイティブ・イメージのパフォー マンス(スループット向上)が最適化される。 手順 1. Javaプログラムのコンパイル → クラスファイルの作成 2. --pgo-instrument オプションを追加してプロファイリング用ネイティブイメージを作成 3. プロファイリング用ネイティブイメージを実行 → プロファイル情報がprofile.iprofに保存 4. プロファイル情報を使って、最適化されたネイティブ・イメージを作成 5. 最適化されたネイティブ・イメージを実行 プロファイルに基づく最適化 (EEのみ) profile-guided optimizations .java .class Native image (プロファイル用) Profile.iprof Native image (最適化済) javac native-image --pgo-instrument (run) native-image --pgo=profile.iprof (run) $ javac OptimizedImage.java $ native-image --pgo-instrument OptimizedImage $ ./optimizedimage $ native-image --pgo=profile.iprof OptimizedImage $ ./optimizedimage

Slide 25

Slide 25 text

Copyright © 2022, Oracle and/or its affiliates 25 タイプ ビルド時オプション 説明 シリアル GC (デフォルト) • 最適化目標=メモリ・フットプリントおよび Java ヒープ・サイズを最小化 • 停止とコピーを行う単純な GC (非パラレル、非同時実行) G1 GC --gc=G1 • 最適化目標=レイテンシとスループットの間のバランス • マルチスレッド GC、stop-the-world の停止を減らしてレイテンシーを改善 • EE でのみ使用可能 / Linux for AMD64 向けイメージのみサポート Epsilon GC --gc=epsilon • ガベージコレクションを行わない=割り当てられたメモリを解放しない • 少量のメモリしか割り当てない非常に短時間で実行されるアプリケーション • GraalVM 21.2 以降で使用可能 ネイティブ・イメージのガベージ・コレクタ

Slide 26

Slide 26 text

Copyright © 2022, Oracle and/or its affiliates 26 システム構成と使用されている GC に基づいて、適切な Java ヒープ設定が自動的に決定される ネイティブ・イメージのコマンド ライン オプションでヒープサイズを明示的に設定することも可能 • -Xmx - 最大ヒープ サイズ (バイト単位) • -Xms - 最小ヒープ サイズ (バイト単位) • -Xmn - young 世代のサイズ (バイト単位) イメージのビルド時にデフォルトのヒープ設定を事前に構成することもできる (GraalVM 20.0以降) 指定された値は、実行時にデフォルト値として使用される • -R:MaxHeapSize - 最大ヒープサイズ (バイト単位) • -R:MinHeapSize - 最小ヒープサイズ (バイト単位) • -R:MaxNewSize - young世代のサイズ (バイト単位) ネイティブ・イメージのヒープサイズ $ ./demo –Xms384m –Xmx1g

Slide 27

Slide 27 text

Copyright © 2022, Oracle and/or its affiliates 27 静的分析で検出しきれない動的機能の使用に関する情報が必要なケースはままある → 人力で動的機能を全て洗い出して設定するのは非常に大変 & 100%補足は困難 トレース・エージェント • 構成ファイルの準備を容易にする • GraalVM javaコマンドのコマンドラインで有効にできる 実行中のJava VMから、クラス、メソッド、フィールド、リソースを参照したりプロキシ・アクセスをリクエストするすべてのコー ルをインターセプトして、ネイティブ・イメージ作成のための構成情報を出力する • オプション config-output-dir=... 構成ファイルの出力先ディレクトリ config-merge-dir=... ファイルを上書きせずにマージするときはこちらを使用 config-write-period-secs=... 定期的な書き込みを行う秒数 config-write-initial-delay-secs=... 最初の書き込みまでの時間 caller-filter-file=...コール元メソッドによるフィルタ設定 access-filter-file=...アクセス対象によるフィルタ設定 トレース・エージェント $JAVA_HOME/bin/java -agentlib:native-image-agent= -cp … MainClass

Slide 28

Slide 28 text

Copyright © 2022, Oracle and/or its affiliates 28 ネイティブ・イメージ作成のためのビルド・プロセスを支援するプラグイン • ネイティブ・イメージの作成 • JUnitを使ったテストのサポート • テストもネイティブ・イメージにコンパイルして実行することができる • トレース・エージェントの起動 • アプリケーション実行時、テスト時のエージェント有効化 • 到達可能性メタデータリポジトリ (GraalVM Reachability Metadata Repository) のサポート (0.9.13以降) • 静的分析によって検出されない要素を含めるためのメタデータリポジトリ github.com/oracle/graalvm-reachability-metadata/tree/master/metadata • ライブラリ/フレームワークのメタデータをリポジトリで共有・再利用することによってビルド作業を効率化 • GraalVM ネイティブ ビルド ツールはメタデータ・リポジトリの使用を有効化できる • native-maven-plugin の で URL を指定する ネイティブ ビルド ツール Maven プラグイン, Gradle プラグイン pom.xml で native-maven-plugin を “native” プロファイル内で package/testフェーズに 紐付けている $ mvn -Pnative -Dagent=true test $ mvn –Pnative test $ mvn -Pnative (-DskipTests=true) (-DskipNativeTests=true) package

Slide 29

Slide 29 text

Copyright © 2022, Oracle and/or its affiliates 29 自動検出 – ある程度のものはネイティブ・イメージ ビルダーが自動的に検出してくれる • Class.forName(String) の Stringがリテラルの場合など 構成ファイル • 自力で記述する and/or agentを使って構成ファイルを出力する org.graalvm.nativeimage.hosted.Feature インターフェースの実装クラスを作成する • 構成ファイル相当の情報を Java クラスとして記述する ネイティブ・イメージ構成情報の渡し方 [{ "name": "com.example.Hello", "methods": [ { "name": "", "parameterTypes": [] }, { "name": "say", "parameterTypes": [] } ] }] reflect-config.json package com.example; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.hosted.RuntimeReflection; public class RuntimeReflectionRegistrationFeature implements Feature{ public void beforeAnalysis(BeforeAnalysisAccess access) { try { RuntimeReflection.register(Hello.class); RuntimeReflection.register(Hello.class.getDeclaredConstructor()); RuntimeReflection.register(Hello.class.getDeclaredMethod("say")); } catch (NoSuchMethodException /*| NoSuchFieldException*/ e) {} } } =

Slide 30

Slide 30 text

Copyright © 2022, Oracle and/or its affiliates 30 ネイティブ・イメージでも利用可能だが制限がある • カスタム/システム・イベント、ディスク・ベースのレコーディング • スタックトレース、メモリ・リーク・ディテクション等は未実装 • GraalVM JDK 11でビルドされたネイティブ・イメージのみ 使い方 • ビルド時 native-image -H:+AllowVMInspection JavaApplication • 実行時 ./javaapplication -XX:+FlightRecorder -XX:StartFlightRecording="filename=recording.jfr(,…)“ • JFRシステムのログ設定のオプションもあり: -XX:FlightRecorderLogging=[tag1[+tag2...] ネイティブ・イメージと JDK Flight Recorder

Slide 31

Slide 31 text

Copyright © 2022, Oracle and/or its affiliates 31 デモ: ネイティブ・イメージを作成する ネイティブ・イメージ・ビルダー トレース・エージェント Maven プラグイン リフレクション対応 – 構成ファイル / Feature

Slide 32

Slide 32 text

Copyright © 2022, Oracle and/or its affiliates 32 ネイティブ・イメージ ~ 実践編

Slide 33

Slide 33 text

Copyright © 2022, Oracle and/or its affiliates 33 「ネイティブ・イメージ対応」 の意味するところ • ネイティブ・イメージの作成で引っかかりそうな動的機能を使わないようにフレームワークが作られている • e.g.) アノテーションの処理を実行時でなくビルド時に行う • 構成ファイルや Feature クラスが ライブラリの jar ファイルに同梱されている マイクロサービス・フレームワークのネイティブ・イメージ対応 メジャーなマイクロサービス・フレームワークはネイティブ・イメージに対応している状況 但し、自分で import する 3rd party ライブラリなどがネイティブ・イメージに 対応している訳ではないので、楽観的過ぎてはダメ ( トレース・エージェントのお陰でずっと楽にはなりました… )

Slide 34

Slide 34 text

Copyright © 2022, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted 34 Helidon = マイクロサービス向けの軽量Javaフレーム ワーク、OracleがホストするOSSプロジェクト ネイティブ・イメージの作成をサポート SE, MP ともに各コンポーネントのネイティブ・イメージ 対応状況に関するリストを提供 ポイント • Helidon の流儀を崩さない “mvn package –Pnative-image” • トレース・エージェントを使って構成ファイルを生成 • 配置場所の慣習に従って配置 • 最後はトライ&エラーで設定を追加 Helidon アプリケーションをネイティブ・イメージにして動かす helidon.io https://qiita.com/tkote/items/a7f9a7b3ba9633cd83c7 $ mvn clean package -Pnative-image

Slide 35

Slide 35 text

Copyright © 2022, Oracle and/or its affiliates 35 デモ:Helidon MP ネイティブ・イメージ Hibernate (JPA) を使って Oracle データベースにアクセスする Java アプリケーションを ネイティブ・イメージにコンパイルして動かす

Slide 36

Slide 36 text

Copyright © 2022, Oracle and/or its affiliates 36 起動時間が早い → コールド・スタート問題を緩和できる • コールド・スタートとは? • 初回の呼び出し(アプリケーションの設定値変更後を含む)が遅い ← コンテナを新規に準備するため • 一定時間アイドル状態が続いた後での呼び出しが遅い ← コンテナが一旦破棄されているため初回呼び出しと同じになる • その要因は? • コンテナ起動に関する準備に要する時間 → FaaS が提供する Provisioned Concurrency 機能で対策可能 • コンテナ内のアプリケーションのウォームアップに要する時間 → Java の場合、このオーバーヘッドが大きい メモリ・フットプリントが小さい → 低コストで運用できる • OCI Functions の場合、課金単位は 「リクエスト数 + ギガバイト・メモリ-秒」 ネイティブ・イメージと FaaS (Function as a Service) 相性がいいとされている理由 コンテナ起動時間 Javaアプリのウォームアップ時間 コールド・スタート問題の緩和! Provisioned Concurrency Native Image

Slide 37

Slide 37 text

Copyright © 2022, Oracle and/or its affiliates 37 OCI Functions フルマネージドなサーバレス基盤(FaaS) • 様々な用途で利用可能 • イベント処理、RESTサーバー、API GW認証処理、etc. • 実行時のみ課金、インフラ管理不要、自動スケール オープンソースのFn Projectをベース • Dockerコンテナの可搬性、ロックイン無し 開発者視点のシンプルな開発フロー • CLI: fn [ init | build | deploy | … ] • 開発キット(FDK)を提供 • Java, Node.js, Python, Go, Ruby Function Development Kit for Java github.com/fnproject/fdk-java (オープンソース) 入出力、データバインディング、Junitテスト機能などのAPIとラ ンタイムを提供し、Dockerイメージ作成をサポート OCI Functions でネイティブ・イメージを動かす (1) OCI Functions とは / FDKで作成されるコンテナ・イメージ Functions FDKで作成されるコンテナ・イメージと OCI Functions ランタイムの構成 OCI Functions コンテナ・ホスト・インスタンス unix domain socket /tmp/xxxxx.sock Fn コンテナ・イメージ OS libfnunixsocket.so JVM runtime-x.x.x.jar api-x.x.x.jar アプリケーション jar リクエストを fwdする 何か FDKで 作成される もの 3rd party jars JNI

Slide 38

Slide 38 text

$ mvn test Copyright © 2022, Oracle and/or its affiliates 38 ネイティブ・イメージのコンテナは作れそう • カスタム Dockerfile で fn build すれば OK • この中で native-image ツール (mvn) を動かす • libfnunixsocket.so は、FDKランタイム・イメージ からコピーする ネイティブ・イメージ 構成ファイルをどう生成するか? • ローカル環境では、fn コンテナの起動は難しい • 諸々の前提条件が必要なのでかなりタフ • → テスト・ハーネスを使ってアプリケーションをテストす るタイミング(mvn test)で agent を起動 • maven-surefire-plugin のオプションで – agentlib:xxx を指定する* • access-filter.json でJUnit系の構成情報をフィルタ 必要に応じて、マニュアルで構成ファイルを編集・追加 OCI Functions でネイティブ・イメージを動かす (2) ネイティブ・イメージの Fn コンテナを作成するための方法を紹介 Fn コンテナ・イメージ OS libfnunixsocket.so JVM runtime-x.x.x.jar api-x.x.x.jar アプリケーション jar 3rd party jars JNI ネイティブ・イメージ ここを ネイティブ・イメージに コンパイルする ローカルテスト実施に agent を起動して ネイティブ・イメージ構成ファイルを自動生成 自前の Dockerfile でコンテナ作成 * native-maven-plugin 使うより融通が利く (設定ファイルを上書きせずマージするオプションを指定できる) ので、こちらの方法を取りました 構成 ファイル $ fn build

Slide 39

Slide 39 text

Copyright © 2022, Oracle and/or its affiliates 39 OCI Functions でネイティブ・イメージを動かす (3) fn build で使用する Dockerfile ### STEP 1 – ネイティブ・イメージ・ビルダの入ったパブリック・コンテナ・イメージを使ってソースコードをビルドして、アプリケーションのネイティブ・イメージを作成する FROM ghcr.io/graalvm/native-image:ol8-java17-22.1.0 as native-image-build WORKDIR /function ADD pom.xml pom.xml ADD mvnw mvnw ADD .mvn .mvn RUN ["./mvnw", "package", "-DskipTests=true"] ADD src src RUN ["./mvnw", "-Pnative", "package", "-DskipTests=true"] # ネイティブ・イメージ (func) は /function/target 下に作成される ### STEP 2 - fdk ランタイム・イメージから libfnunixsocket.so をコピーするための準備 FROM fnproject/fn-java-fdk:jre11-latest as fdk-runtime # libfnunixsocket.so is located under /function/runtime/lib ### STEP 3 – fn 仕様のコンテナ・イメージを作成する func + libfnunixsocket.so FROM container-registry.oracle.com/os/oraclelinux:8-slim WORKDIR /function COPY --from=native-image-build /function/target/func . # copy native image COPY --from=fdk-runtime /function/runtime/lib/libfnunixsocket.so . # copy libfnunixsocket.so ENTRYPOINT ["./func", "-XX:MaximumHeapSizePercent=80", "-Djava.library.path=/function"] CMD [ "com.example.fn.HelloFunction::handleRequest" ]

Slide 40

Slide 40 text

Copyright © 2022, Oracle and/or its affiliates 40 デモ:OCI Functions でネイティブ・イメージを動かす Eclipselink (JPA) を使って Oracle データベースにアクセスする Java アプリケーションを ネイティブ・イメージにコンパイルして OCI Functions で動かす Autonomous Database Functions Key Vault DB PW resource principal

Slide 41

Slide 41 text

Copyright © 2022, Oracle and/or its affiliates 41 Micronaut (micronaut.io) • マイクロサービス/サーバーレスアプリケーションを構築するためのJVMベースのOSSフレームワーク ネイティブ・イメージを作成するためのガイドが各種あり (guides.micronaut.io) • CREATING YOUR FIRST MICRONAUT GRAAL APPLICATION • DEPLOY A MICRONAUT FUNCTION (SERVERLESS) APPLICATION TO ORACLE CLOUD • DEPLOY A MICRONAUT HTTP API GATEWAY FUNCTION (SERVERLESS) APPLICATION TO ORACLE CLOUD ↑ ちなみに 「MICRONAUT + ORACLE CLOUD」 のセクションに、 MySQL, IDCS, Secrets, Database, Streaming, Email Delivery など、各種サービスとのインテグレーションに関するガイドがあります! (たいていのものはバイトコードに加えてネイティブ・イメージの作成まで解説アリ) Micronaut ネイティブ・イメージを OCI Functions で動かす AOTに優しいフレームワーク – Javaアノテーションの処理を実行時からコンパイル時にシフト これがミソ = HTTP Verb/Path に応じた制御部分をフレームワーク側でやってくれる=開発・保守生産性向上 → Java FDK ではやってくれない部分 @Delete("/{countryId}") public void deleteCountry(int countryId) { … これを 待ってた!

Slide 42

Slide 42 text

Copyright © 2022, Oracle and/or its affiliates 42 デモ:Micronaut native-image FaaS API Server このデモ = ガイド "DEPLOY A MICRONAUT HTTP API GATEWAY FUNCTION (SERVERLESS) APPLICATION TO ORACLE CLOUD" + ガイド "ACCESS A DATABASE WITH JPA AND HIBERNATE" API Gateway Autonomous Database Functions Key Vault User DB PW GET POST PUT DELETE resource principal

Slide 43

Slide 43 text

Copyright © 2022, Oracle and/or its affiliates 43 デモ:Micronaut native-image FaaS API Server API Gateway の設定 API Gateway Autonomous Database Functions Key Vault User DB PW GET POST PUT DELETE resource principal /country から始まる任意のパスで GET/POST/PUT/DELETE メソッドの HTTP リクエストは sandbox アプリケーションの mn-function-http ファンクションに ルーティングする

Slide 44

Slide 44 text

PART 3: 言語ランライムとツール Copyright © 2022, Oracle and/or its affiliates 44

Slide 45

Slide 45 text

Copyright © 2022, Oracle and/or its affiliates 45 • ゲスト言語の実行環境=コンテキスト (org.graalvm.polyglot.Context) からゲスト言語を実行する • ゲスト言語の関数を実行する • ゲスト言語の変数 (オブジェクト) にアクセスする • ゲスト言語から ホスト環境の Java オブジェクトにアクセスする • ゲスト言語から Java クラスにアクセスする Java にポリグロット言語を埋め込む (Embedding) 主な機能 Context context = Context.create(); context.eval("js", "print('Hello JavaScript!');"); Value function = context.eval("js", "x => x+1"); int x = function.execute(41).asInt(); // 42 context.getBindings("js").putMember("javaObj", new BigDecimal(3)); context.eval("js", "print(javaObj.pow(2));"); // 9 Value result = context.eval("js", "({array: [1,2,8,16]})"); int v = result.getMember("array").getArrayElement(2).asInt(); // 8 Context context = Context.newBuilder().allowAllAccess(true).build(); context.eval("js", "Java.type('java.lang.System').out.println('Hello World!');");

Slide 46

Slide 46 text

Copyright © 2022, Oracle and/or its affiliates 46 起動方法 • $JAVA_HOME/bin/js --polyglot --jvm Java を呼び出す • 前頁のとおり、Java.type(クラス名) を使う 他の言語を呼び出す • Polyglot.eval(“<ゲスト言語>”, “<ゲスト言語で書かれたスクリプト>") 言語ランタイムから他の言語を呼び出す JavaScript の例 var array = Polyglot.eval("python", "[1,2,42,4]"); // array print(array[2]); // 42 var datetime = Polyglot.eval("python", "import datetime¥ndatetime.datetime"); // type print(datetime.now().isoformat()); var now = Polyglot.eval("python", "import datetime¥ndatetime.datetime.now()"); // object print(now.isoformat()); JavaScript から Python を呼び出す import datetime datetime.datetime import datetime datetime.datetime.now()

Slide 47

Slide 47 text

Copyright © 2022, Oracle and/or its affiliates 47 Rhino, Nashorn の代替 • GraalVMに は互換性のための起動オプションあり JVMのスレッドプールを使ったマルチスレッド実行 • ワーカースレッドにポリグロット・コンテキストを割り当てる • ロシアの大手SNSで、JS (React) を使った HTML レンダリング処理をサーバーサイドで実行した例 https://prog.world/new-odnoklassniki-frontend-launching-react-in-java-part-i/ 他の GraalVM 言語 (Java, Ruby, Python, LLVM, R, etc.) とデータとコードを共有 • npm ライブラリでは未提供の機能を Java ライブラリで代替するなどの活用法が考えられる • Neo4J の Java ライブラリを色々な言語から使ってみた例 https://github.com/michael-simons/neo4j-graalvm-polyglot-examples/ GraalVM ツールのサポート - Insight, VisualVM, Chrome Debugger, VS Code extensions, etc. • Node.js アプリケーション に Java/GraalVM エコシステムの恩恵を与えることができる JavaScript/Node.js with GraalVM GraalVM で JavaScript コードを実行する積極的理由を考えてみた

Slide 48

Slide 48 text

Copyright © 2022, Oracle and/or its affiliates 48 プログラムのランタイム動作をトレースして、情報を取得したり、処理を記述したりするためのツール • 実行プログラムとは別にプログラム (polyglot対応) を記述して、実行時にアタッチする • $JAVA_HOME/bin/node --insight= <アプリケーション.js> • 設定したトレースポイント (‘source’, ‘enter’, ‘return’, ‘close’) のイベントでの処理を記述 • 変数の参照 • 変数の値の変更 • 例外の送出 • メソッドのインターセプト • 実行スタックの参照 • ヒープダンプの取得 GraalVM Insight https://www.graalvm.org/tools/graalvm-insight API (Javadoc でちょっと分かりにくい…) https://www.graalvm.org/tools/javadoc/org/graalvm/tools/insight/Insight.html 実行アプリ Insight プログラム GraalVM アタッチ --insight insight.on('enter', function(ev) { var cnt = map.get(ev.name); ... }, { roots: true });

Slide 49

Slide 49 text

Copyright © 2022, Oracle and/or its affiliates 49 • Chrome DevTools Protocol の組込み実装を提供 • Chrome Developer Toolsなどの互換性のあるデバッガをGraalVMにアタッチできる Chrome デバッガ ゲスト言語アプリケーションのデバッグ >c:¥opt¥java¥graalvm-ee-java11-22.2.0¥bin¥node --jvm --inspect server.js Debugger listening on ws://127.0.0.1:9229/x1N0pf3jcy7y9BOW4oB2wnr1AH2Pqyg48cy63uInp7Q For help, see: https://www.graalvm.org/tools/chrome-debugger E.g. in Chrome open: devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/x1N0pf3jcy7y9BOW4oB2wnr1AH2Pqyg48cy63uInp7Q ブレークポイント ステップ実行 変数の参照 etc.

Slide 50

Slide 50 text

Copyright © 2022, Oracle and/or its affiliates 50 GraalVM に関するサポートを追加 • 実行中の GraalVM プロセスの監視 • ネイティブ イメージ プロセスの基本的な監視 • ゲスト言語レベルでのアプリケーションの分析 (Graal Sampler、Heap Viewer) • JavaScript、Python、Ruby、R 言語をサポート Graal VisualVM All-in-One Java Troubleshooting Tool

Slide 51

Slide 51 text

Copyright © 2022, Oracle and/or its affiliates 51 デモ:Node.js on GraalVM Node.js アプリケーションを Insight で実行状況を確認する Node.js アプリケーションを Chrome デバッガでデバッグする Node.js アプリケーションを VisualVM でモニタ/プロファイルする Virtual Machine Autonomous Database Key Vault VisualVM GraalVM Node.js App モニタ/プロファイル GraalVM Node.js App Chrome デバッグ GraalVM Node.js App Insight Insight

Slide 52

Slide 52 text

まとめ Copyright © 2022, Oracle and/or its affiliates 52

Slide 53

Slide 53 text

Copyright © 2022, Oracle and/or its affiliates 53 GraalVMの基本機能 • GraalVM JIT Compiler, AOT Compiler, Truffle ネイティブ・イメージ作成のためのツール群 • ネイティブ・イメージ ビルダー • トレース・エージェント • Maven プラグイン, Gradle プラグイン ネイティブ・イメージ作成に対応したフレームワーク • Helidon, Micronaut, Spring Native, Quarkus, ... • OCI Functions FDK でネイティブ・イメージを作成 ポリグロット機能と開発支援ツール • Insight, Debugger, VisualVM まとめ 最初に登場した頃に比べて 各段に使いやすくなっているので 過去一度幻滅?した方も含めて 是非最新版の GraalVM を 試してもらいたいです!

Slide 54

Slide 54 text

Copyright © 2022, Oracle and/or its affiliates 54 ドキュメンテーション • GraalVM https://www.graalvm.org/docs/ • Oracle GraalVM Enterprise Edition 日本語ドキュメンテーション https://docs.oracle.com/cd/F44923_01/index.html • Helidon AOT https://helidon.io/docs/v3/#/se/aot https://helidon.io/docs/v3/#/mp/aot • Micronaut https://docs.micronaut.io/ 記事 • Javaに革命を起こすGraalVM Native Image https://www.infoq.com/jp/articles/native-java-graalvm/ • Micronautフレームワークを使ったクラウドネイティブJava https://www.infoq.com/jp/articles/native-java-micronaut/ デモ・ソース • GitHub https://github.com/oracle-japan/ochacafe-graalvm 参考資料

Slide 55

Slide 55 text

Thank you Copyright © 2022, Oracle and/or its affiliates 55