効率的な java dynamic aop システムを実現する just-in-time weaver
DESCRIPTION
効率的な Java Dynamic AOP システムを実現する Just-in-Time weaver. 佐藤芳樹 千葉滋 東京工業大学大学院 情報理工学研究科. 【発表のあらまし】 効率的な Java Dynamic AOP システム を実現する手法を提案 AOP: アスペクト指向プログラミング 提案手法を実装した Wool を説明. [ BookShelf ] Book search(String key) { Logger.info( “ in BookShelf#search() ” ); - PowerPoint PPT PresentationTRANSCRIPT
Jan 23-24, 2003 PRO-2002-4, Nagoya 1
効率的な Java Dynamic AOP システムを実現する
Just-in-Time weaver
佐藤芳樹 千葉滋
東京工業大学大学院情報理工学研究科
【発表のあらまし】効率的な Java Dynamic AOP システム を実現する手法を提案
AOP :アスペクト指向プログラミング提案手法を実装した Wool を説明
Jan 23-24, 2003 PRO-2002-4, Nagoya 2
アスペクト指向とはモジュール間にまたがる横断的関心事( crosscutting concerns) をアスペクトとしてモジュール化
0. AOP(Aspect-Oriented-Programming)
[Book] boolean match(String key) { if (match0(key)) return true; else return false; }
[ BookShelf ] Book search(String key) { while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; }
どこかで無限ループしてるからメソッドの出入りをロギング
してみよう!!
[ BookShelf ] Book search(String key) { Logger.info(“in BookShelf#search()”); while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; Logger.info(“out BookShelf#search()”); }
[Book] boolean match(String key) { Logger.info(“in Article#match()”); if (match0(key)) { Logger.info(“out Article#match()”); return true; } else { Logger.info(“out Article#match()”); return false; } }
あちこちに散らばるコードcrosscutting concern
分散、同期、セキュリティトランザクション、 etc…
[ BookShelf ] Book search(String key) { while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i];
}
[Book] boolean match(String key) {
if (match0(key))
return true; else
return false; }
Aspect
ロギング処理をプログラムと別に記述
search と match の前後Logger.info(…)
Aspect
search と match の前後Logger.info(…)
アスペクトとプログラムを静的に合成 (weave)
weaverweaver
[Book] boolean match(String key) { Logger.info(“in Article#match()”); if (match0(key)) { Logger.info(“out Article#match()”); return true; } else { Logger.info(“out Article#match()”); return false; } }
[ BookShelf ] Book search(String key) { Logger.info(“in BookShelf#search()”); while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; Logger.info(“out BookShelf#search()”); }
Jan 23-24, 2003 PRO-2002-4, Nagoya 3
Dynamic AOP とその利点アスペクトとプログラムを実行時に合成するDAOP が注目されている
1. 研究の背景
1.down
2.rebuild(recompile,reweave)
3.restart
1.dynamic weave
アプリケーションを止めずにロギングの on/offやパッチ当て
1.開発サイクルの高速化
・配置・解像度・ビットレート・色数 etc…
aspects
2 .適応的なサービスアスペクト
要求、環境に応じサービスを動的にカスタマイズ
分散 GUI アプリケーション
Jan 23-24, 2003 PRO-2002-4, Nagoya 4
AOP を実現するモデル・フィールド アクセス・メソッド 呼び出し
・オブジェクト 生成
・・
・
join-point でアドバイスを実行する適切に定義された コードの断片実行フロー上のポイント
Dynamic Join Point Model(AspectJ[*1] で提案 )
pointcut 場所の指定(join-point を指定 )advice 処理の記述
アスペクト
*1 Xerox Corporation. “The AspectJ Programming Guide. Online Documentation”, 2001. http://www.aspectj.org/
2. Dynamic AOP
join-point
match()search()
Logger.info()
Jan 23-24, 2003 PRO-2002-4, Nagoya 5
フックによる典型的な実装アスペクトとプログラムの合成
= 静的コード変換によるフック挿入 join-point にあたる場所にフックを挿入 フックにより実行がインターセプトされ適切なアド
バイスを実行
2. Dynamic AOP
joinpoint
pointcut指定
フック
挿入されたフックコード
do_before_advice();do_after_advice();
do_before_advice();do_after_advice();
Jan 23-24, 2003 PRO-2002-4, Nagoya 6
既存の Java DAOP システムDAOP システムを実現するためには、実行時にフックを挿入する機能が必要
動作リフレクション ( 演算を横取りし変更できる機能 )
• CLOS 、 Smalltalk 、 etc
処理系の改造 可搬性を損なう
静的コード変換 低品質のコードを生成 → 次に説明
2. Dynamic AOP
Jan 23-24, 2003 PRO-2002-4, Nagoya 7
静的コード変換すべての join-point へ静的にフックを挿入 静的にフックを挿入する場所を特定できない アドバイスを実行するかどうかをチェック
2. Dynamic AOP
チェックのための分岐、無駄なフックによるコードサイズの肥大化常にすべての join-point でチェック
低品質のコードを生成長時間稼動するサーバアプリに問題
need_advice();need_advice();
need_advice();need_advice();
need_advice();
need_advice();need_advice();
need_advice();need_advice();need_advice();need_advice();need_advice();
pointcut での指定はここだけ
Jan 23-24, 2003 PRO-2002-4, Nagoya 8
ジャストインタイム フック埋め込み・の提案
フックを挿入するためにデバッガによる手法と動的クラス書き換え手法をハイブリッド
1 .デバッガによるフック挿入・実行(PROSE[*2])
• フックを breakpoint として挿入• デバッガがアドバイスを実行
2 .動的クラス書き換え (我々が開発 )• コード変換でフックを挿入+ロード済みクラスの再定義• 再定義を可能な限り遅延
3. ジャストインタイム・フック埋め込み
*2 Andrei. P, Thomas. G and Gustavo. A. “Dynamic Weaving for Aspect-Oriented Programming” In AOSD’02
Jan 23-24, 2003 PRO-2002-4, Nagoya 9
デバッガによるフック挿入・実行
フックを breakpoint で挿入 (PROSE[*2]) breakpoint で実行をインターセプト+アドバイス
実行• 実行コードに無駄なフック無し• JPDA( デバッガ ) を使用し可搬性を損なわない
3. ジャストインタイム・フック埋め込み
breakpoint セット
*2 Andrei. P, Thomas. G and Gustavo. A. “Dynamic Weaving for Aspect-Oriented Programming” In AOSD’02
デバッガdo_advice();
デバッガデバッガがアドバイス実行
Jan 23-24, 2003 PRO-2002-4, Nagoya 10
動的クラス書き換えフックをコードに埋め込む 必要になるまで遅延し、 Just-in-Time に埋め込む
• 無駄なフックを挿入しない その後は高速にアドバイスを実行 HotSwap 機能を使用 (Sun JDK1.4 JPDA)
• デバッガの制御下でロード済みクラスを再定義できる機能
3. ジャストインタイム・フック埋め込み
JPDAJVM
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
ロード済みクラス
クラス再定義フック入りクラス
Jan 23-24, 2003 PRO-2002-4, Nagoya 11
do_advice();デバッガ
ハイブリッドした手法二段階のフック埋め込み 初めにフックはすべて breakpoint として挿入 選択的に動的クラス書き換え
3. ジャストインタイム・フック埋め込み
do_advice();do_advice();
do_advice();do_advice();デバッグモード (-Xdebug)
で HotSpot 実行
③-2動的クラス書き換え対象プログラムがアドバイス実行
③-1デバッガがアドバイス実行デバッガ
① アスペクトが weaveし join-point が判明 ② 指定されたすべて
の join-point へbreakpoint をセット
Jan 23-24, 2003 PRO-2002-4, Nagoya 12
ハイブリッドする必要性使用頻度の高いアドバイス デバッガがアドバイス実行 → アドバイス実行がボトルネック
使用頻度の低いアドバイス 高価な動的クラス書き換え → 変換がボトルネック
フック埋め込み時間
動的クラス書き換え
デバッガ
アドバイ
ス実行時間
ハイブリッド標準でデバッガがアドバイス実行
3. ジャストインタイム・フック埋め込み
システムロードに応じ効果的に動的コード書き換え
トレードオフ
Jan 23-24, 2003 PRO-2002-4, Nagoya 13
JIT コンパイラとの比較JIT コンパイラの動作との類似点・相違点 類似点
• オンデマンドにコード変換• 性能向上のために 2種類の実行法をハイブリッド
相違点• weave 後にコードのセマンティクスが変更=>weave 時に active なフレームへの配慮が必要
実行の途中で書き換えられるメソッドでのアドバイス 依存関係のあるアドバイス
3. ジャストインタイム・フック埋め込み
Jan 23-24, 2003 PRO-2002-4, Nagoya 14
実行途中で書き換えられるメソッド
active フレームではデバッガがアドバイス実行
HotSwap 時に active なフレームが参照するクラスは変更されない (JPDA の仕様 )
3. ジャストインタイム・フック埋め込み
active フレーム = 実行途中のメソッド
do_advice();do_advice();
クラス定義は元のまま
weave 後に積まれるフレームは変更後の
クラスを参照
アドバイスが実行されず一貫性が崩れる
do_advice();
BookShelf#search()
Book#match()
Book#match0()
Jan 23-24, 2003 PRO-2002-4, Nagoya 15
依存関係のあるアドバイスactive フレームでのデバッガのアドバイス実行の有無は手動で選択 before アドバイスは実行されていない after アドバイスの実行はユーザが選択
3. ジャストインタイム・フック埋め込み
デバッガbefore
after
デバッガafter
before が実行されていなくても after のみ実行
例: search メソッドの前後で時間を計り検索時間を測定する機能を アスペクトで追加
BookShelf#search()
Book#match()
Book#match0()
Jan 23-24, 2003 PRO-2002-4, Nagoya 16
全体の流れjoin-point でアドバイス実行手法を選択= 動的に切り替え → 各問題を解決
3. ジャストインタイム・フック埋め込み
デバッガによる実行
デバッガによる実行
選択的に実行
動的クラス書き換え
埋め込まれたアドバイス実行
active フレーム
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
active フレーム アドバイスが
実行されない
アドバイス間
に依存関係
ボトルネックの除去
Jan 23-24, 2003 PRO-2002-4, Nagoya 17
Wool の実装ジャストインタイムフック埋め込みを Java用に実装した Just-in-Time weaver JPDA で breakpoint セットとクラス再定義、 Javassist でバ
イトコード変換
4. Wool
JVM JPDA
Javassist
バイトコード変換
Wool
クラス再定義do_advice();do_advice();
aspects
+
breakpoint セット、アドバイス実行
Jan 23-24, 2003 PRO-2002-4, Nagoya 18
Wool の起動法1. 外部プログラムから起動 => 開発サイクルの高
速化
2. アプリケーションが起動 => サービスアスペクトの実現
4. Wool
WlAspect pda = WlAspect.forName(“PDAAspect”);WlAspect pc = WlAspect.forName(“PCAspect”);Wool wool = Wool.connect(“somedomain”,5432);switch(client) {case PDA : wool.weave(pda);case PC : wool.weave(pc);}
% wool –weave LoggingAspect –address islisp.ysk.csg.private% wool –unweave LoggingAspect –address islisp.ysk.csg.private
Jan 23-24, 2003 PRO-2002-4, Nagoya 19
アドバイス実行手法選択の記述アスペクトプログラムから Wool を制御する機構
• コンテキストに応じてアドバイス実行手法を選択• 外部から weave する場合、反映されるタイミングが不定
4. Wool
Wool の初期化合成の前後切り離しの前後
コールバックメソッドに各タイミングでWool を制御するコードを記述する
例public void beforeWeave(Wool wool) { if (wool.joinMethodExit()) wool.skip();}public void afterWeave(Wool wool) { if (wool.countActiveFrame() > 0) wool.regardActiveFrame();}
メタな処理 ( 実行フロー外のポイント ) なので join-
point では表現しない
Jan 23-24, 2003 PRO-2002-4, Nagoya 20
比較実験実験環境
Arch : SunBlade1000 、CPU : UltraSPARC-III 750MHzX2 、 Memory : 1GBOS : Solaris8JVM : Sun J2SDK1.4.0 HotSpotTMClient VM
Wool現在は最初の join-point で必ず動的クラス書き換え
実験プログラム1. SpecJVM98 の jess2. 自然数の和を求める再帰メソッド
5. 性能測定
Jan 23-24, 2003 PRO-2002-4, Nagoya 21
結果と考察 (1)
5. 性能測定
目的-実行時間と合成処理にかかる時間の測定 (active フレーム処理無し )方法-ナンバーパズル〈 N〉、モンキーバナナ〈M〉 〈 1〉 protected メソッド (4of146 、 734615回呼び出し ) に null アドバイス 〈 2〉 1つのメソッド (1of146 、 1338回呼び出し ) に null アドバイス結果
考察 ・アドバイス実行回数が多いほど良い結果、少ないほど動的クラス書き換 えのオーバーヘッド ・ join-point抽出+変換再定義を差し引いた実行時間が AspectJ に近い
5回計測の最小値単位 [msec]
AspectJデバッガ手
法 Wool
総実行時間のうちわけ
join-point抽出 変換再定義 実行時間
〈 N〉〈 1〉 8590 7388812 19638 1680 4057 13901
〈 N〉〈 2〉 8522 23307 11832 1680 806 9376
〈M〉
〈 1〉1063 45817 11003 1680 4057 5266
〈M〉
〈 2〉1003 3833 3993 1680 806 1507
Jan 23-24, 2003 PRO-2002-4, Nagoya 22
結果と考察 (2)
5. 性能測定
目的-デバッガでの active フレーム処理の性能劣化方法- sum() 実行中に null アドバイスを weave active フレームの個数を変化結果
0
5000
10000
15000
20000
25000
30000
0 5 10 20 40 60 80 100 120 140 160 180 200
activeフレームの個数
[ms]
処理
時間
デバッガ手法 Wool
考察 ・デバッガでのアドバイス実行回数が多いほど性能劣化 ・扱う active フレームが 0 の場合性能劣化がだいぶ小さい
26000
2500
Jan 23-24, 2003 PRO-2002-4, Nagoya 23
まとめと課題ジャストインタイム・フック埋め込みを提案し、 Java用の weaver である Wool を Java で実装した 実行時に無駄なフックの無い良質のコードを生成 アスペクトと合成後に高速実行 weaver を柔軟に制御する機能を提供今後の課題 追加実験(静的コード変換) 未実装機能の実装 (Introduction,around アドバイス ) パフォーマンスチューニング 動的プロファイラの実装
6. まとめ
Jan 23-24, 2003 PRO-2002-4, Nagoya 24
別の実装手法 1アドバイス実行方式の選択を自動化 手動選択 ( 現在 )
• アドバイス実行方式を手動で選択できる機構 自動選択
• 環境 ( システムロードなど ) に応じ適切な実行方式を選択
HotSpot技術のように動的プロファイラで実行時の傾向をプロファイリング
7. 別の実装手法
アドバイスの実行回数が閾値を超える => 動的クラス書き換えを施す
Jan 23-24, 2003 PRO-2002-4, Nagoya 25
別の実装手法 2自己反映的な OpenJIT で実装
• アスペクトのディレクティブでコンパイルコードを変更• 動的に再コンパイル
メソッド単位でアスペクトの合成• 無駄なフックの挿入をより抑えられる
同様の active フレーム対応処理
さらなる高速化が期待できるが可搬性を損なうので現実的ではない
7. 別の実装手法
Jan 23-24, 2003 PRO-2002-4, Nagoya 26
アスペクトの記述
付録
public class LoggingAspect extends WlAspect { WlCrosscut record = pointcut("*","BookShelf","search", "(Ljava/lang/String;)V").joinCall(); public void doit() { teach(new WlBeforeAdvice(record) { public void advice(TargetInfo tinf) { Target t = tinf.getTarget(); Logging.info(“in ” + t.className()+”#”+t.name()); } }); } public void initWeave(Wool wool) throws Exception { wool.filter(" ^java.*|^sun.*“,false); }}
ポイントカット記述
アドバイス記述
weaver の制御記述
Java でのアスペクト記述
Jan 23-24, 2003 PRO-2002-4, Nagoya 27
do_advice();
デバッガによるフック挿入・実行
付録
Jan 23-24, 2003 PRO-2002-4, Nagoya 28
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
動的コード書き換え
付録
Jan 23-24, 2003 PRO-2002-4, Nagoya 29
do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();
do_advice();do_advice();do_advice();do_advice();
ジャストインタイム・フック埋め込み (ハイブリッド )
付録