Oracle Direct Seminar <Insert Picture Here> 高速 JVM Oracle JRockit の全貌入門編
Agenda JRockitとは JRockitの内部動作について JRockitの運用監視について 2
概要 JRockit とは? BEA(Oracle) が提供 & サポートする Java SE 完全準拠の JVM もともとサーバサイド用途専用に作られた JVM( 現在はクライアントサイド用途にも対応 ) Intel アーキテクチャ (Xeon,Itanium2) へ最適化された業界最速の JVM( 現在は Sparc 版も提供 ) 歴史 1998 年スウェーデンアピールバーチャルマシンより初版がリリース 2002 年 BEA がアピールバーチャルマシンを買収 2008 年 Oracle が BEA を買収 Sun J2SE との互換性 java version でベースとなる Sun J2SE のバージョンを表示 R27.5 java version "1.5.0_14" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_14-b03) BEA JRockit(R) (build R27.5.0-110-94909-1.5.0_14-20080204-1558-windows-ia32, compiled mode) R27.6 java version "1.5.0_15" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_15-b04) BEA JRockit(R) (build R27.6.0-47_o-99698-1.5.0_15-20080603-2103-windows-ia32, compiled mode) JRockit に含まれる各種ツール JavaAPI は基本的に J2SE と同一だが J2SE では定義されていない部分 ( ネーティブコード生成 最適化 メモリ管理 独自ツール等 ) を BEA が固有実装 3
レスポンスタイム (ms) オンメモリで自動記録 JRockit Java SE 完全準拠の高機能 JVM 高速 : サーバーサイド用途に最適化 公式ベンチマークで実証済み 安定 : GC による遅延時間の平準化 ミリ秒単位の応答時間の維持を実現 全てを記録 : 稼動状況を常に記録 予測外の事態でも過去に遡って分析可能 #1 パフォーマンス ( 高速 ) 公式ベンチマーク (SPECjbb) 処理性能数値の世界最高値 JVM あたりの性能数値の世界最高値 WebLogic Server 性能を犠牲にすることなく全ての挙動を記録 実行時情報 不測の GC 処理 処理の滞留 タイムアウト GC を JVM で制御 ( 安定 ) JRockit VM 1 0 1 0 0 0 0 1 1 1 1 1 0 1 0 破棄 Time 300 300 250 200 150 100 通常 JVM 250 200 150 100 JRockit Real Time 設定された時間枠 ( 例 : 前 5 分間 ) の稼動情報をオンメモリで常時保持 何か起きても過去に遡って分析可能 4
JRockit の特長 - The Server Side Java VM - サーバサイド Java の特徴と要求 特徴 マルチプロセッサマシンでの利用 長時間稼動 大きなメモリヒープサイズ Synchronizationの多用 動的なクラスローディングの多発 小さい単位の処理を多くのスレッドで並行実行 ソケット通信やファイルI/Oの多用 要求 高信頼性 可用性 / 管理性 拡張性 性能 クライアントサイドでの Java の利用とは異なった特徴と要求 5
JRockit の特長 - The Server Side Java VM - Java VM 処理の比重 CG = Code Generation クライアント サーバ MM = Memory Management TM = Thread Management MM R TM IO R CG I/O R = Reflection CG MM TM クライアントとは異なるサーバサイドの処理要求に特化した Java VM が必要 6
JRockit の特長 - 高速性 - Higher performance leads to significant cost savings 公式ベンチマークで証明された高速性 SPECjbb2005 トップ 10 のうち 6 つが JRockit (Last publication update: Jun 3 2010 ) 7
Agenda JRockitとは JRockitの内部動作について JRockitの運用監視について 8
そもそも JVM とは? Java ソースコード バイトコード 配布 実行 コンパイル 中間コード JVM JVM JVM JVM JVM Solaris HP-UX AIX Linux Windows Any Hardware ランタイム OS ハードウェア JVM(Java Virtual Machine) Java プログラムの実行環境 - バイトコードを 1 行ずつ機械語 (machine code) に変換し実行 - 各 OS の機能を覆い隠す役割も担う 9
JRockit アーキテクチャ ~ ネーティブコード生成 ~ Sun JVM の場合 バイトコードのままインタープリタで実行 メソッドの実行回数を常時監視 実行回数が閾値 (-XX:CompileThreshold) を超えたメソッドをコンパイルしてネーティブコードを生成 byte code インタプリタ実行 1 メソッド実行 回数監視 2 コンパイル 3 native code ネーティブ実行 JRockit の場合 1 2 3 各メソッドの初回実行時にバイトコードをJITコンパイルしてネーティブコードを生成バックグランドで動くサンプルスレッドが定期的にアプリケーション スレッドの状態を監視し 頻繁に使用されているメソッドをリストアップまだ最適化されていないメソッドのうちで最も使用頻度が高いメソッドをより高速なネーティブコードへ最適化 byte code JIT コンパイル native code アプリスレッド監視 最適化 native code+ 1 ネーティブ実行 2 3 ネーティブ実行 10
コード最適化を示す例 最適化されたコードでは クラス A を実行するたびにクラス B を実行する必要がない 11
JRockit アーキテクチャ ~ スレッドローカルエリア (TLA)~ TLA が無いと 各スレッドはオブジェクトをアロケートするたびにヒープのロックを得る必要があるので遅い Thread 1 Thread 2 Thread 3 a = new Object(); b = new Object(); c = new Object(); Heap lock TLA が有れば 各スレッドの専用エリアにオブジェクトをアロケートできるので速い ( もちろんアロケート済みオブジェクトは他スレッドからも利用可能 ) Thread 1 Thread 2 Thread 3 a = new Object(); b = new Object(); Heap lock c = new Object(); TLA for Thread 1 TLA for Thread 2 TLA for Thread 3 TLA for Thread 1 12
JRockit アーキテクチャ ~ メモリレイアウト ~ Java の オブジェクト は Sun JVM でも JRockit でもヒープに置かれる Java の クラス は Sun JVM では Permanent 領域 JRockit では Native 領域に置かれる JRockit では Sun JVM における Survivor(From&To) に相当する領域は無く Nursery がフルになると Old にすぐに昇格する よって JRockit では 初回 GC で生き残ったオブジェクトは全て以降は Full GC のチェック対象になるが Full GC が発生しても問題ないような様々な工夫がされている JRockit では高速化等を目的に Sun JVM には無い様々な情報が Native 領域に置かれる Sun JVMの場合ヒープ New Eden Survivor From To 0 1 32 Xmn Xmx/Xms JRockit の場合ヒープ Nursery 0 1 Xns Xmx/Xms Old Old 最大 32 回でプロモーション Perm anent Native -XX:PermSize -XX:MaxPermSize 1 回でプロモーション Native 13
ご参考 Parallel GC と Concurrent GC 従来の GC では GC を一つのスレッドで実行し その間アプリケーションスレッドは停止 (STOP-THE-WORLD) していました そのためマルチ CPU マシンで GC の間待機する CPU が存在しスループットが低下する原因となりました これへの対策が GC を複数スレッドで実行するパラレル GC アプリケーションを止めずに GC を 1 スレッドで実行するコンカレント GC です 従来の GC STOP-THE- World!! Parallel STOP-THE-World!! Concurrent CPU に処理が割り当てられず性能が低下 14
JRockit ガーベッジ コレクション 1 Parallel Garbage Collection (for New GC and Old GC) JVM は 1CPU あたり 1GC スレッドを並列に使用して一気に GC を行う GC の間はアプリケーションスレッドは完全に止まるが トータルでのアプリケーションのスループットは最も高くなる Java application threads Garbage Collector threads 15
JRockit ガーベッジ コレクション 2 Mostly Concurrent Garbage Collection (for Old GC) 1 つの GC 専用のスレッドが GC 処理のほとんどのフェーズをアプリケーションと同時に行う GC 中のアプリケーションのスループットは落ちるものの 停止は避けられる Java application threads Garbage Collector thread GC スレッドがヒープ内のオブジェクトの移動と削除を行うときのみ 短時間アプリケーションスレッドが止まる 16
JRockit アーキテクチャ ~ ガーベッジ コレクション ~ ガーベッジ コレクション方式の指定方法 動的 GC 重視する指針のみを指定し GC アルゴリズムについては JRockit が内部で最適な組み合わせを動的に選択 重視する指針 アプリケーションのスループット ( デフォルト ) 個々の GC ポーズタイムの短縮 アプリのレスポンスタイム (JRockit Real Time でのみ利用可能 ) 指定方法 -XgcPrio:throughput -XgcPrio:pausetime -XpauseTarget=<n>ms -XgcPrio:deterministic - XpauseTarget=<n>ms 17
JRockit Real Time 従来の Java では困難だった予測可能なレスポンスを実現 120 従来の Java JRockit Real Time 105 120 90 75 105 60 45 90 30 15 0 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 低トランザクション時 :GC による一部タイムアウトが発生しうる 75 60 45 120 105 90 75 60 45 30 15 0 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 高トランザクション時 : GC による停止により レスポンスタイムが劣化する 30 15 0 0 2000 4000 6000 8000 10000 12000 14000 16000 18000 JRockit Real Time は Deterministic GC により GC 停止時間を抑制 安定したレスポンスを提供アプリケーションに手を入れる必要なし 18
Deterministic GC - JRockit Real Time Mostly Concurrent GC をさらに改善 1 世代ヒープ (Nursery と Old 間の参照や移動のコストを削減 ) 個々の PauseTime の制限付け (-XpauseTarget=XXms) ただし あくまで努力目標 アプリ特性とヒープ設定によっては守れないことも アプリスレッドを止めなければならない GC のフェーズをパラレル化 オブジェクトの生成速度を随時観察し GC のスケジュールを最適化 例 ) ヒープ全体を一度に GC するのではなく 複数回の短い GC に分割 例 ) ヒープが一杯になる前に早めに GC を開始 例 ) 開始した GC が予定時間内に終わりそうにない場合に 一旦 GC を中止し 可能なら残作業を次回 GC に繰り越し Java application threads Garbage Collector threads 19
JRockit 動的 GC アルゴリズム別性能比較 スループット優先 GC ポーズタイム優先 GC Deterministic GC ポーズタイム スループット レスポンス 20
Agenda JRockitとは JRockitの内部動作について JRockitの運用監視について 21
JRockit Mission Control JRockit 専用の GUI ベースの運用監視ツール TCP/IP ベースのプロトコルでリモートの JRockit プロセスの運用監視が可能 監視される JRockit 側は以下のオプションでポートを開けるだけ ( エージェント等のインストール不要 ) 例 : -Xmanagement:port=7091,ssl=false,authenticate=false 機能一覧 Management Console: CPU 使用率 ヒープ使用状況 スレッド使用状況 MBean 監視 Memory Leak Detector: 迅速なメモリリーク検出 オブジェクトの参照関係の階層表示 JRockit Flight Recorder: GC 詳細情報 ホットパッケージ ホットメソッド情報 22
Management Console リアルタイムに JVM の内部情報を取得 CPU 使用状況 (JVM/Machine) メモリ使用状況 (JVM/Machine) をグラフ表示 任意の MBean 情報の閲覧 更新 グラフ化 トリガ アラートの設定 スレッド情報 ( スタックトレース CPU ビジー デッドロック有無 ) の確認 メソッドプロファイリング Management Console のオーバヘッドは非常に小さく ほとんど無視できる程度 大部分の情報は JRockit 特有の MBean として常時更新されているため 但し 監視対象の JRockit と同一マシンでの Management Console 起動は GUI 負荷が高くなるため推奨しない 23
Memory Leak Detector メモリーリーク監視 診断機能 稼働中の JRockit プロセスに接続してリアルタイムに傾向を取得 サンプル中の Object 増加数 サイズ インスタンス数 ヒープ中における割合 各 Object を参照している Object スタックを階層的に表示が可能 ガベージコレクションのマーク フェーズを巧みに利用してヒープ上のクラス別メモリ統計情報を取得しているため オーバヘッドがほとんどなく監視可能 (JVM 開発ベンダーだからこそ可能な方法 ) 24
JRockit Flight Recorder 突然のトラブルに対する新アプローチ 2010.07 New Release! as JRockit (R28) with WebLogic 10.3.3 これまでの Java Java EE/ISV アプリ App Server JVM ダンプを解析 Full thread dump Java HotSpot(TM) Client VM (1.5.0_06-64 mixed mode, sharing): "Low Memory Detector" daemon prio=5 tid=0x0050a600 nid=0x1816a00 runnable [0x00000000..0x00000000] "CompilerThread0" daemon prio=9 tid=0x00509cb0 nid=0x1816600 waiting on condition [0x00000000..0xf0b06358] "Signal Dispatcher" daemon prio=9 tid=0x00509840 nid=0x1816200 waiting on condition [0x00000000..0x00000000] "Finalizer" daemon prio=8 tid=0x00509020 nid=0x1810200 in Object.wait() [0xf0a04000..0xf0a04ab0] at java.lang.object.wait(native Method) - waiting on <0x26580360> (a java.lang.ref.referencequeue$lock) at java.lang.ref.referencequeue.remove(referencequeue.java:116) - locked <0x26580360> (a java.lang.ref.referencequeue$lock) at java.lang.ref.referencequeue.remove(referencequeue.java:132) at java.lang.ref.finalizer$finalizerthread.run(finalizer.java:159) "Reference Handler" daemon prio=10 tid=0x00508c30 nid=0x180f200 in Object.wait() [0xf0983000..0xf0983ab0] at java.lang.object.wait(native Method) - waiting on <0x26580a50> (a java.lang.ref.reference$lock) at java.lang.object.wait(object.java:474) at java.lang.ref.reference$referencehandler.run(reference.java:116) - locked <0x26580a50> (a java.lang.ref.reference$lock) "main" prio=5 tid=0x005013a0 nid=0x1804c00 waiting on condition [0xf07ff000..0xf08002c0] at java.lang.thread.sleep(native Method) at ThreadTest1.method1(ThreadTest1.java:7) at ThreadTest1.main(ThreadTest1.java:4) "VM Thread" prio=9 tid=0x00508450 nid=0x1803c00 runnable "VM Periodic Task Thread" prio=9 tid=0x0050bcb0 nid=0x1813000 waiting on condition "Exception Catcher Thread" prio=10 tid=0x005015e0 nid=0 JRockit Flight Recorder Java EE/ISV アプリ Oracle WebLogic Server JRockit VM 直近 ( 例 : 24 時間 ) の実行時情報を記録し続ける 自動記録 5% 以下の低負荷 問題解決に必要な情報の多くは消失 原因究明に多くの時間が必要 履歴を含めた情報を記録し自動出力 迅速な原因究明を支援する GUI ツール 1. トラブルの確実な原因追究を 遡って 実施可能 2. 障害発生 改善のサイクルと手間を大きく短縮化 25
26
27
28
JRockit 診断コマンド ~jrcmd~ 同一マシン上で稼働中の JRockit インスタンスに対してコマンドを発行して JRockit 内部の様々な情報を得たり 動作設定を変更することが可能 jrcmd <pid> <command> 主要コマンド start_management_server kill_management_server startjrarecording stopjrarecording print_object_summary print_class_summary print_threads print_memusage runsystemgc verbosity help JRMCポートを開ける JRMCポートを閉じる JRAレコーディングを開始 JRAレコーディングを停止クラス別インスタンス数 / メモリ使用量など表示クラスロードされているクラスを全て表示スレッドダンプを表示メモリ領域 (Heap/Nativeなど) ごとの使用状況表示 Full GCを強制実行冗長ログの出力項目 / 出力先の変更使用可能なコマンド一覧 各コマンド使用方法 29
以上の事項は 弊社の一般的な製品の方向性に関する概要を説明するものです また 情報提供を唯一の目的とするものであり いかなる契約にも組み込むことはできません 以下の事項は マテリアルやコード 機能を提供することをコミットメント ( 確約 ) するものではないため 購買決定を行う際の判断材料になさらないで下さい オラクル製品に関して記載されている機能の開発 リリースおよび時期については 弊社の裁量により決定されます Oracle PeopleSoft JD Edwards 及び Siebel は 米国オラクル コーポレーション及びその子会社 関連会社の登録商標です その他の名称はそれぞれの会社の商標の可能性があります 30
31
ご参考 GC アルゴリズム概要 JVM 一般 マーク & スイープアルゴリズム JRockit を含め多くの Java VM は マーク & スイープアルゴリズムによって GC 対象となるオブジェクトを決定し オブジェクトが利用していたヒープ領域を回収します オブジェクトの移動 ( コンパクションとプロモーション ) 生存中のオブジェクトがヒープ全体にちらばると 空き領域の連続長が短くなります これをフラグメンテーションが進んだ状態と呼び大きなオブジェクトの生成時の領域確保に失敗する可能性を秘めています 生存中のオブジェクトを移動し 十分に連続した空き領域を確保する処理をコンパクションと呼びます 特に世代管理されたヒープで世代間に渡ってオブジェクトを移動することをプロモーションと呼びます 実際にはオブジェクトの移動はスイープフェーズの一部として行われますが 論理的には別フェーズと考える方が単純です マークフェーズ スイープフェーズ コンパクション / プロモーションフェーズ 1 回の GC 32 32
ご参考 マークフェーズ JVM 一般 マークフェーズでは 全てのスレッド ( ルートセット ) からオブジェクトの参照を辿り 参照可能 ( 利用されている ) なオブジェクト全てに利用中マークをつける処理が行われます ルートセット スレッド 1 スレッド 2 スレッド 3 スレッド 4 レレレレ チェックの付かなかったオブジェクトが GC の対象となる レ レ レ レ レ レ レ 33 33
ご参考 スイープフェーズ JVM 一般 スイープフェーズでは ヒープを端から走破して マークの付いていないオブジェクト を回収します 回収された領域は前後の空き領域と合わせられ 空き領域リストとして管理されます ヒープ領域 レレレレレレレ アドレス 領域長 空き領域リスト 34 34
ご参考 コンパクションフェーズ JVM 一般 コンパクションフェーズでは 利用中のオブジェクトを移動 ( 再配置 ) して大きな空き領域を作成します オブジェクトの移動に伴い そのオブジェクトへの参照も全て書き換えられます JNI で利用されている等 Java VM が参照を全て把握できないオブジェクトは移動できずピンドオブジェクトと呼ばれます ヒープ領域 コンパクション 35 35