220 likes | 314 Views
豊富な情報を基にした pointcut を記述できるアスペクト指向言語. 東京工業大学大学院 情報理工学研究科 数理・計算科学専攻 千葉研究室 02M37220 中川 清志. アスペクト指向 (AOP). オブジェクト指向の限界 ある種の処理は複数クラスに散らばる ロギング,同期,永続性などの処理 アスペクト指向の利点 そのような処理をアスペクトとしてモジュール化 クラスとアスペクトは分離して記述 オブジェクト指向を補完. AOP の目標:図形エディタの例. Screen. 目標: 「 図形の外観変化を起こすメソッド 」 の後に Screen を更新したい
E N D
豊富な情報を基にした pointcutを記述できるアスペクト指向言語 東京工業大学大学院 情報理工学研究科 数理・計算科学専攻 千葉研究室02M37220 中川 清志 2003年度 修士論文発表会
アスペクト指向(AOP) • オブジェクト指向の限界 • ある種の処理は複数クラスに散らばる • ロギング,同期,永続性などの処理 • アスペクト指向の利点 • そのような処理をアスペクトとしてモジュール化 • クラスとアスペクトは分離して記述 • オブジェクト指向を補完 2003年度 修士論文発表会
AOPの目標:図形エディタの例 Screen • 目標:「図形の外観変化を起こすメソッド」の後にScreenを更新したい • 図形クラスからScreen更新命令 最終的には図形クラス内のdraw() メソッドが呼ばれる FigureElement draw() Point Line int x, y Point p1, p2 getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() これらのメソッドの最後にはScreenを更新するコードが必要 2003年度 修士論文発表会
AOPの目標:図形エディタの例「従来の方法では」AOPの目標:図形エディタの例「従来の方法では」 void setP1(Point newP) { p1 = newP;} void move(int dx, int dy) { p1.move(dx, dy); p2.move(dx, dy);} screen.update(); • 更新のための命令が各クラス、メソッドに散らばってしまう • 保守性・再利用性が悪い FigureElement draw() screen.update(); Point Line void setX(int newX) { x = newX;} void move(int dx, int dy) { x += dx; y += dy;} int x, y Point p1, p2 screen.update(); getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() screen.update(); 2003年度 修士論文発表会
screen.update(); screen.update(); screen.update(); screen.update(); AOPの目標:図形エディタの例「AOPでは」 void setP1(Point newP) { p1 = newP;} void move(int dx, int dy) { p1.move(dx, dy); p2.move(dx, dy);} screen.update(); • 更新のための命令を分離して記述 • 処理系 weaver により合成 アスペクト: これらのメソッドの 最後にはscreen.update()を 実行せよ FigureElement draw() Point Line void setX(int newX) { x = newX;} void move(int dx, int dy) { x += dx; y += dy;} int x, y Point p1, p2 getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() 2003年度 修士論文発表会
screen.update(); screen.update(); screen.update(); 「どこに合成したいか?」をどのように指示するかが問題!! 「どこに合成したいか?」をどのように指示するかが問題!! screen.update(); AOPの目標:図形エディタの例「AOPでは」 void setP1(Point newP) { p1 = newP;} void move(int dx, int dy) { p1.move(dx, dy); p2.move(dx, dy);} screen.update(); • 更新のための命令を分離して記述 • 処理系 weaver により合成 アスペクト: これらのメソッドの 最後にはscreen.update()を 実行せよ FigureElement draw() weaver Point Line void setX(int newX) { x = newX;} void move(int dx, int dy) { x += dx; y += dy;} int x, y Point p1, p2 getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() 2003年度 修士論文発表会
AspectJ*における合成箇所の指定方法の問題点 • コードを挿入するメソッドを全て書き並べる必要あり • しかし、保守性・再利用性が悪い • 見落とす可能性がある 例えばLine.rotate(..)というメソッド • メソッドの追加、名前変更などに弱い FigureElement call(void Point.set*(int))|| call(void Point.move*(..))|| call(void Line.set*(Point))|| call(void Line.move*(..)) draw() Point Line int x, y Point p1, p2 getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() 2003年度 修士論文発表会 * Kiczales等 ECOOP1997
必要とされる合成箇所の指定方法 • 深い情報を基にして、コードを挿入するメソッドを指定したい • メソッド名を書き並べなくてもよい FigureElement 「“draw”メソッドの中で読み込まれるフィールドのどれか」をそのボディ中で更新するような、“Point”クラス内の全てのメソッド draw() Point Line int x, y Point p1, p2 getX()getY()setX(int)setY(int)move(int,int)draw() getP1()getP2()setP1(Point)setP2(Point)move(int,int)draw() つまりは赤い枠内のメソッド 2003年度 修士論文発表会
pointcut の記述力が高いAOP言語 Josh • きめ細かい「どこに合成するか(pointcut)」の指示が可能 • pointcut 記述言語の拡張 • Java で拡張 • リフレクションの使用 • Javassist[Chiba00] を使用 • 汎用的な「何を合成するか」の記述 • 合成箇所の情報を利用したインタータイプ宣言 本発表は、前者の「pointcut」についてのみ説明する 2003年度 修士論文発表会
この箇所にアスペクト合成決定!! pointcutのメカニズム joinpointメソッド呼び出し フィールド参照 インスタンス生成 etc. • アスペクトの合成場所の指定 • 言い換え:joinpoint (実行点)の選別作業 • 条件と対象joinpoint のペア 例: • 「setXという名前の」メソッド呼び出し • 「Lineクラスの」フィールド参照 プログラム 対象 joinpoint 条件:名前が setX pointcut 2003年度 修士論文発表会
pointcut の記述方法 • pointcut 指定子を使い記述 • 指定子は、対象joinpoint と選別方針を持つ 例:call (“void *.setX(..)”) • 「void 型の“setX”で引数とクラス名は任意」というメソッド呼び出しを指定 • call は pointcut 指定子で、メソッド呼び出しが対象 • カッコ内は条件 2003年度 修士論文発表会
Josh が提供する強力な pointcut の原理 • pointcut指定子をユーザが新たにJavaで定義可能 • joinpoint の選別方針をJavaで定義 • 従来は言語組み込みの指定子のみ使用可 • joinpoint をJavaのオブジェクトで表現して公開 • そのjoinpointの情報を得るメソッドを提供 • リフレクションを使い豊富な情報を入手 2003年度 修士論文発表会
pointcut指定子 boolean 型メソッド before : call (“void Point.setX()”) { /* アドバイスボディ */ } • pointcut 指定子を boolean 型のメソッド呼び出しへ変換 • 新たに boolean メソッドを定義すれば指定子として使用可能 コード変換器 アドバイスボディとは指定された箇所で実行されるコード断片 if ( call( jp, “void Point.setX()”, jc)) { /* アドバイスボディ挿入 */ } jp : Java で表現されたjoinpoint のオブジェクト jc : joinpoint に 関連する情報を持つ 2003年度 修士論文発表会
新たなpointcut指定子の定義例(1/2)[引数の決まりごと]新たなpointcut指定子の定義例(1/2)[引数の決まりごと] 使用例:simpleCall(“setX”) 例:simpleCall というpointcut指定子を定義 • 第一引数で対象とするjoinpointを指定 • ここではメソッド呼び出し • Stringの配列で、条件を受け取る • args[0] = “setX” • JoshContext は有用な情報を保持 static boolean simpleCall (MethodCall m,String[] args, JoshContext jc) { String name1 = m.getMethodName(); String name2 = args[0]; return name1.equals(name2);} 内容:メソッド呼び出しの中で、メソッド名が“setX”というものを選別する 2003年度 修士論文発表会
新たなpointcut指定子の定義例(2/2)[ボディの記述]新たなpointcut指定子の定義例(2/2)[ボディの記述] 使用例:simpleCall(“setX”) • name1 : • このメソッド呼び出しjoinpointにおいて、呼び出されたメソッド(callee)の名前 • joinpointオブジェクトから入手 • name2 : • この例ではname2 = “setX” • name1とname2が一致したら真を返す static boolean simpleCall (MethodCall m,String[] args, JoshContext jc) { String name1 = m.getMethodName(); String name2 = args[0]; return name1.equals(name2);} 内容:メソッド呼び出しの中で、メソッド名が“setX”というものを選別する 2003年度 修士論文発表会
複雑なpointcut指定子の定義例[図形エディタ問題の解決]複雑なpointcut指定子の定義例[図形エディタ問題の解決] • updater 指定子を定義 • 図形エディタの問題を解決 • リフレクションの使用 • より深い情報を得られる static boolean updater(MethodCall mc, String[] args, JoshContext jc) { CtClass root = jc.getCtClass(args[0]); String mname = args[1]; Hashtable fields = enumerateFields(root, mname); CtMethod mth = mc.getMethod(); mth.instrument(new ExprEditor() { public void edit(FieldAccess expr) { String name = expr.getFieldName(); if (expr.isWriter() && fields.get(name) == expr.getCtClass()) return true; } return false;} 内容:「drawメソッドで読み込まれるフィールドを更新する」メソッド呼び出しを選別する 使用例:updater(“Point”, “draw”) 2003年度 修士論文発表会
Josh 処理系の全体図 .josh独自言語で書いた アスペクト .class アスペクト埋め込みのターゲット weaver コード変換器 .class pointcut 指定子の定義 pointcut の使用 & アドバイス .class アスペクトとクラスの両方の機能 2003年度 修士論文発表会
比較実験 • 実験内容 • Josh と AspectJ の 性能比較 • weave時間 • weave済みプログラムの実行時間 • 実験環境 • SunBlade1000 • UltraSPARC-III 750MHzX2, Memory 1GB • Solaris8 • Sun JDK 1.4.0_01, AspectJ 1.1b2 2003年度 修士論文発表会
実験(1) • weave 対象:XML解析器 Xerces • アスペクト:全ての public メソッド呼び出しの前にカウンタをいれる • 結果 • Josh の方が weave 時間は少ないが実行時オーバヘッドがある • コード長が大きくなっている • アドバイスをインライン展開しているため 2003年度 修士論文発表会
JoshAspectJ 実験(2) • weave対象:JavaGrande ベンチマークプログラム • アスペクト:あるクラスのオブジェクトを対象としたメソッド呼び出しの前にカウンタをいれる • 結果 • 先ほどと同様に、Josh は weave 時間が少ないが実行時オーバヘッドがある • AspectJ は最適化に力をいれているため [秒] weave 時間 [秒] 実行時間 JavaGrande ベンチマークの種類 2003年度 修士論文発表会
関連研究 • アスペクト指向言語 • AspectJ • Hyper/J • Composition Filters • pointcut の拡張 • pointcut を論理型言語で記述 • Brichau等 [GPCE2002] • Gybels等 [AOSD2003] 2003年度 修士論文発表会
まとめ • アスペクト指向言語 Josh を提案 [AOSD2004] • pointcut に関して高い記述力を持つ • pointcut 指定子を新たに Java で定義できる • 複雑な pointcut が可能 • 汎用的な指定子は組み込みで与える • 複雑なものだけを自分で定義すればよい • Josh の性能を AspectJ と比較 • コンパイル時間は少ないが、実行時のオーバヘッド有り 2003年度 修士論文発表会