100 likes | 190 Views
実行中のプログラムの 振舞いを安全に拡張できるアスペクト指向システム. 東京工業大学理学部情報科学科 02-0878-1 栗田 洋輔. 背景. AOP (Aspect-Oriented Programming) ポイントカット-プログラム実行中のあるポイントを指定するもの アドバイス - ポイントカットで指定されたポイントから呼び出されるようになる手続き アスペクト-通常のフィールド・メソッドの他、複数のポイントカットやアドバイスも含むことができるモジュール Dynamic AOP プログラムの実行を止めずに、プログラムの外からアスペクトを追加(織り込み)・削除できる
E N D
実行中のプログラムの振舞いを安全に拡張できるアスペクト指向システム実行中のプログラムの振舞いを安全に拡張できるアスペクト指向システム 東京工業大学理学部情報科学科02-0878-1 栗田 洋輔
背景 • AOP (Aspect-Oriented Programming) • ポイントカット-プログラム実行中のあるポイントを指定するもの • アドバイス - ポイントカットで指定されたポイントから呼び出されるようになる手続き • アスペクト-通常のフィールド・メソッドの他、複数のポイントカットやアドバイスも含むことができるモジュール • Dynamic AOP • プログラムの実行を止めずに、プログラムの外からアスペクトを追加(織り込み)・削除できる • アドバイスが活性化される順序に注意しなければならない • 活性化 ‐ アドバイスが実行可能になること アスペクト • フィールド • メソッド • ポイントカット • アドバイス 対象プログラム
顧客数=X 顧客数=X+1 顧客数=X+1 顧客数=X 顧客数=X 顧客A 顧客数=X-1 顧客B 顧客A セッション 時間 アドバイス活性化の順序関係を考慮しない場合の問題 • 例: ショッピングサイトでのプロファイリング • プロファイリングを始めた時点以降にログインした顧客の情報を元にリアルタイムに統計をとる プロファイリング用アスペクト 顧客 int 顧客数; ログイン用アドバイス ログイン 顧客数 ++; アスペクトの織り込み(顧客数=X) アスペクトの織り込み(顧客数=X) アスペクトの織り込み(顧客数=X) ログアウト用アドバイス 顧客数 --; ログアウト ログイン、ログアウトという順序でアドバイスは活性化されなければなら ない。また、アドバイスの活性化はセッションごとに考える必要がある。 あるセッションでの活性化は他のセッションとは独立しているべき。
本研究の成果 • アドバイスが活性化される順序を宣言的に定義できる Dynamic AOP System を開発した • AND, OR, NOT による組み合わせ • 例: logoutAdvice.follows(loginAdvice); • 例: A.follows( new AND( new NOT(B), C) ); • セッションを自由に定義できるようにした • スレッドの ID • プログラムの実行時の値 • 例: 顧客のID • セッションごとにアドバイスが独立して活性化されるようにした
PCut loginPCut = MethodEntryPCut .getInstance("Shopping", "login(Customer)"); PCut logoutPCut = MethodExitPCut .getInstance("Shopping", "logout(Customer)"); Advice loginAdvc = new Advice(loginPCut) { public void adviceBody(Context context) { incCounter(context); /* プロファイル情報を表示 */ }}; Advice logoutAdvc = new Advice(logoutPCut) { public void adviceBody(Context context) { decCounter(context); /* プロファイル情報を表示 */ }}; registerAdvices(loginAdvc, logoutAdvc); logoutAdvc.follows(loginAdvc); setSessionPolicy(new SessionPolicy() { public Object getSessionID(Context context) { return getCustomerID(context); } }); ポイントカット定義 アドバイス定義 アドバイスの登録 アドバイスを活性化する順序の定義 セッションの定義 アスペクトの例 public class ProfilingAspect extends Aspect { int headCounter = 0; //総顧客数 int ageSum = 0; //総年齢 // 総顧客数と総年齢を加算・減算する private void incCounter(Context context){} private void decCounter(Context context){} // コンストラクタ public ProfilingAspect() { }} /* 右の図 */
既存システムとの比較 Key: アドバイス と 顧客のID Value: 実行されたかどうかのフラグ • 既存システムでも、順序関係を明示的に記述することはできる • アスペクト内に、どのアドバイスが実行されたかという情報を持つ変数を定義し、アドバイス内からその変数を参照・変更する • 問題点 • アスペクトを書くプログラマに大きな負担 • コードのサイズが大きくなってしまう。 • アドバイスの順序関係の定義が複数のアドバイスに分散してしまう。 • モジュール性・可読性が低い • 順序関係を手続き的に記述する • エラーが発生しやすい Map executedAdvices; int 顧客数; ログイン用アドバイス • この顧客のログイン用アドバイス • が実行されたことを • executedAdvices に登録 • 顧客数を1つ増やす ログアウト用アドバイス • もし、この顧客のログイン用 • アドバイスが実行されていなけ • れば、すぐに return する。 • 顧客数を1つ減らす
本システムの実装 • Java Platform Debugger Architecture (JPDA) を利用 • Debugger 上でアドバイスを実行する • アドバイスを呼び出したいところに、ブレークポイントを設定する Thread Breakpoint Advice Context Switch Debuggee VM Debugger VM
全てのブレークポイントが設定されたことの確認全てのブレークポイントが設定されたことの確認 • アドバイスを順序関係にもとづいて活性化するためには、全てのブレークポイントがセットされていることを確認しなければならない • 複数のブレークポイントが同時に設定されることを期待してはいけない • とりあえず全てのブレークポイントを設定し、アドバイスを実行するか否かは後から判断する • ブレークポイントはキューから順番に取り出される • 全てのポイントにブレークポイントを設定した後、 もう一度同じポイントにブレークポイントを設定する 全てのポイントにブレークポイントが設定された保証はない ので、アドバイスは実行しない ブレークポイント の設定位置 全てのポイントにブレーク ポイントとが設定されている ので、アドバイスは実行可能
関連研究 • DAC++ • メソッドごとに変数の参照・変更箇所を調べてメタデータとして保存し、衝突が発生しなくなるまでアスペクトの活性化を遅らせる • 本研究のシステムはアスペクトではなくアドバイスを単位として粒度の小さい活性化を行うため、活性化が行われるまでの待ち時間が短い • Wool • 織り込み対象プログラムの全てのポイントからアドバイスを呼び出せる状態にするために、全スレッドを止める • 本研究のシステムはスレッドを止める必要がない • PROSE • スレッドを止めずに、織り込み対象プログラムの全てのポイントからアドバイスを呼び出せる状態にすることができる • そのような状態になるまでの時間をシステムが把握できない
まとめと今後の課題 • アドバイスの順序関係を考慮して安全な織り込みを行える Dynamic AOP System を開発した • Dynamic AOP を利用する際にはアドバイスを活性化する順序を考慮することが必要 • 順序関係を宣言的に記述できる API を提供した • 自由に定義できるセッションごとに、順番に活性化が行われる • アドバイスが織り込み対象プログラムから呼び出し可能になったことを確かめる方法を考えた • 今後の課題 • Java の HotSwap(メソッドの中身を動的に置き換えられる) を利用した場合にも、アドバイスが正しい順序で呼び出されるようにする