分散 Java プログラムのための アスペクト指向言語 西澤無我(東工大, CREST) 千葉滋(東工大, CREST) SWoPP2003, Matsue
本研究は 分散プログラミング支援ツールの開発 DJcutter の提案 分散プログラムのモジュール化を促進 モジュール化は、プログラムの可読性の向上 プログラムをメンテナンスし易くなる DJcutter の提案 Java 用のアスペクト指向プログラミング言語 分散プログラムのモジュール化を促進させるためのプログラミング支援ツールを開発 モジュール化は重要で、ユーザにプログラムを理解しやすくする 結果、バグの修正などといったプログラムのメンテナンスも容易になる このような支援ツールの一環として、アスペクト指向の DJcutter という言語を開発 SWoPP2003, Matsue
既存の技術ではモジュール化ができない処理 横断的関心事 オブジェクト指向技術では 異なるモジュール間にまたがってしまう処理 横断的関心事が存在する 分散プログラムの例 分散化した observer パターン Subject と observer が異なるクラス・ホストに存在 現在、モジュール化を試みている処理は、OOPではうまくモジュール化することの難しい異なるクラス間にまたがってしまう処理である これをわれわれは横断的関心事と呼んでいる 横断的関心事はさまざまな分散プログラムに多く存在している 中でも subject と observer が異なるホストに存在するような observer パターンの実装はありがち SWoPP2003, Matsue
分散化した observer パターン グループ図形エディタの説明 ① 利用者がスクリーン上の 図形の位置を変更する ② その図形の位置の変更にとも ないそれぞれのホストのスクリ ーンも更新される 分散化した observer パターンの具体例としてグループ図形エディタを取り上げる グループ図形エディタとは グループのあるユーザがエディタを起動すると、ディスプレイにスクリーンが表示 スクリーン上に点を描画したとすると、グループのエディタを起動しているユーザのスクリーン上にも点が表示される SWoPP2003, Matsue
分散化した observer パターン - モジュール化の困難さ 2 種類の横断的関心事 異なるクラス間を横断する関心事(AspectJ で対応可) 異なるホスト間を横断する関心事 分散版では… Observer 複数のScreen オブジェクトが各ホストに存在する Subject Point, Line オブジェクトの複製が各ホストに存在する (編集中の図形の情報のコピーが各ホストに存在) このような図形エディタなどの分散化した observer パターンはモジュール化するのが困難 なぜならば、 Observer であるスクリーンを表す screen がエディタ利用者のホストごとに存在する また、スクリーン上の点を表す point や 線を表す line といった subject のコピーが各ホストに存在する そのため、分散プログラム内には2種類の横断的関心事が存在する SWoPP2003, Matsue
FigureElement: Subject update(Subject): void 異なるクラス間の横断的関心事 クラス図 FigureElement: Subject observer: Screen Screen: Observer addObserver(Screen) notify(): void update(Subject): void Point Line getX(): int getY(): int setX(int): void setY(int): void getP1(): Point getP2(): Point setP1(Point): void setP2(Point): void 異なるクラス間の横断的関心事として1つのホスト上で必要とされるエディタのクラス図を示す ディスプレイに表示されるスクリーンを表す screen クラス スクリーン上の点や線を表す point, line クラス 問題は、利用者がスクリーンの点の位置を変更した場合 その点を表す point オブジェクトの setx, sety メソッドが呼ばれる そして、その状態の変更のため、スクリーンを update しなくてはならないので、スクリーンに通知しなくてはならない。Notify メソッドを呼ぶ Notify メソッドの内部では、screen の update メソッドが呼ばれている このように、notify メソッドが point, line クラスのソースファイル内に散らばってしまう 横断的関心事: Subject の状態の変更を observer に通知しなくてはならない SWoPP2003, Matsue
異なるクラス間の横断的関心事の モジュール化 アスペクト指向技術(AOP) 横断的関心事をアスペクトと呼ばれるモジュールに分離する技術 AspectJ 汎用的な Java 用 AOP 言語 異なるクラス間の横断的関心事のモジュール化は可能 しかし、異なるホスト間の横断的関心事のモジュール化は困難 このようなクラス間の横断的関心事をモジュール化する技術として AOP が提案されている。 AOP は、横断的関心事をアスペクトと呼ばれるモジュールに集め、普通の Java のクラスから分離することが可能な技術である その中でも、AspectJ という汎用的な Java 用のAOP言語がある。 SWoPP2003, Matsue
AspectJ によるモジュール化 aspect ObserverProtocol { class Point { pointcut subjectChange(Subject s): (call(void Point.setX(int)) || call(void Point.setY(int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point))) && target(s); after(Subject s): subjectChange(s) { s.observer.update(s); }} class Point { void setX(int) { … } void setY(int) { … } int getX() { … } int getY() { … } } class Line { void setP1(Point p) { … … p.setX(int); notify(); … p.setY(int); notify(); … void setP2(Point p) { Point getP1() { … } Point getP2() { … } class Line { void setP1(Point p) { … p.setX(int); … p.setY(int); … } void setP2(Point p) { Point getP1() { … } Point getP2() { … }} 例えば、Line クラスのソースコード内に散らばる notify メソッド呼び出しを AspectJ を利用して、分離しようと考えると、右のようになる。 このように、notify メソッドを呼ぶメソッドをまとめて記述することにより、line クラスに notify メソッド呼び出しをちりばめる必要がなくなる。 SWoPP2003, Matsue
AspectJ の言語仕様 Join point Advice 定義 Pointcut 記述 プログラム実行中の基本要素 例: メソッド呼び出し、メソッド実行、フィールドアクセス Advice 定義 散らばってしまうコードの断片 Before, after, around Pointcut 記述 Advice を実行する join point の指定 Pointcut 指定子 target, call Pointcut 引数: advice に渡す join point の情報 aspect ObserverProtocol { pointcut subjectChange(Subject s): (call(void Point.setX(int)) || call(void Point.setY(int)) || call(void Line.setP1(Point)) || call(void Line.setP2(Point))) && target(s); after(Subject s): subjectChange(s) { s.observer.update(s); } Pointcut 記述で、advice を実行する join point を指定することができる Pointcut 記述は、pointcut 指定子を複数個利用して join point を指定する また、pointcut には引数をとることができ、join point の情報を advice に渡すことができる SWoPP2003, Matsue
異なるホスト間の横断的関心事 - 遠隔ホスト上の observer AspectJ は苦手 Subject の状態の変更を、すべてのホストのスクリーンに遠隔呼び出しで通知 :Screen :Screen AspectJ を利用して先のグループ図形エディタの横断的関心事をモジュール化すると Advice の内部で、複数のホスト上の screen オブジェクトの遠隔参照を利用し、update メソッドをRMIで実現する 一見、これでよさそうに見えるが、実際には :Point Advice 遠隔メソッド呼出 (RMI) :Screen Pointcut SWoPP2003, Matsue
異なるホスト間の横断的関心事 - 散らばる advice 各ホストに Point や Line の複製を配置すると 各ホストに advice が散らばる 各 advice 内では、各ホスト上の Screen の遠隔参照(ポインタ)のコピーを保持していなければならない :Screen RMI Advice :Point :Screen AspectJ は advice と同じホスト上の join point だけしか pointcut できない :Point Advice :Screen Pointcut Advice :Point AspectJ は advice と同じホスト上の join point だけしか pointcut できない SWoPP2003, Matsue
散らばった advice の問題 各ホスト上に散った複数の advice が一つの関心事を実装 プログラミング上好ましくない 全 Screen の遠隔参照(ポインタ)を全 advice 間で共有 コピーを配布 一貫性の管理が面倒 集中管理 一部の advice は proxy?? Proxy の定義は単純だが面倒 このように、AspectJ を利用して、グループ図形エディタをモジュール化すると、それぞれのホスト上の advice 内部で、screen の遠隔参照を取得できなくてはならない。 Screen の遠隔参照の一貫性を保つのは、難しい これは、 SWoPP2003, Matsue
DJcutter の提案 AspectJ の言語仕様を拡張 遠隔ホスト上の join point を pointcut できる 遠隔ホスト上のプログラム実行が join point に達したら advice を呼び出す Advice が分散しない AspectJ の pointcut 機構 :Point Advice Advice DJcutter の pointcut 機構 遠隔 pointcut SWoPP2003, Matsue
DJcutter による分散 observer パターンのモジュール化 アスペクト・サーバ・ホスト Pointcut Advice RMI :Screen RMI :Point RMI :Point この djcutter のpointcut 機構を利用することにより、advice は、ひとつのホスト上にのみ存在すればよく、screen の遠隔参照もそれぞれのホスト上に散らばることはない。 :Screen :Screen Advice が各ホストに 散らばらずにすむ :Point SWoPP2003, Matsue
言語仕様 (1) - Pointcut 記述 AspectJ のサブセットをサポート Within(Type) Target(Id) それぞれのホスト上に存在する Type クラス内の全ての join point を指定 Target(Id) Id と同じ型を引数にとる join point を全て指定 Args(Id, …) Ids と同じ型を引数にとる join point を指定 Call(Signature) Sigunature に一致しているメソッド呼び出しを指定 言語仕様は大体 AspectJ と同じです SWoPP2003, Matsue
言語仕様 (2) - Advice 定義 AspectJ と同様の機能をサポート 拡張: 組み込み変数 $remotehost Before 選択した join point の直前に advice を実行 After 選択した join point の直後に advice を実行 Around 選択した join point 自体に代わり advice を実行 拡張: 組み込み変数 $remotehost Advice を呼び出した join point の存在するホスト名を String 型で表す Remote host 変数により、 SWoPP2003, Matsue
言語仕様(3) - アスペクトフィールド・メソッド クラス定義と同様のフィールド・メソッドをアスペクト内に定義可能 普通のクラスからアスペクトメソッドを呼び出したい場合 普通のクラスとアスペクトメソッドとは異なるホスト上に存在する場合が多い。 ユーザはインターフェースを経由 aspect LoggingAspect implements Logger { void displayLog(Point p, int x) { … … }} Interface Logger extends AspectInterface{ void displayLog(Point p, int x); } JavaRMI の registry server Aspect クラスは djcutter が用意する実行時ライブラリのクラスである。このクラスの static メソッド get を利用すると、アスペクトへのインスタンスが得られる Logger logger = (Logger) Aspect.get(“LoggingAspect”, this); Logger.displayLog(); アスペクト・メソッドの呼び出し SWoPP2003, Matsue
実装 DJcutter は アスペクトのソースファイルを処理するコンパイラ 分散プログラムを実行する実行時ライブラリ アスペクト・サーバ 拡張クラスローダ SWoPP2003, Matsue
DJcutter コンパイラ アスペクトのソースファイルを Java のクラスに変換する Bytecode 変換 aspect LoggingAspect { pointcut logX(Point p): (call(void Point.setX(int) || call(void Point.setY(int)) && target(p); after(Point p, int x): logX(p, x) { System.out.println(“set x: “ + x); } class LoggingAspect { static void after_$0(Point p, int x) { System.out.println(“set x: “ + x); } このとき、アスペクトのメンバであるフィールドやメソッドは、普通の java のクラスのフィールドやメソッドへ変換される また、advice は static メソッドに変換される Bytecode 変換 SWoPP2003, Matsue
アスペクト・サーバ プログラム実行時に最初に起動 アスペクトのソース内の pointcut 情報をクライアントに配布 アスペクトのソースをコンパイルして得られたクラスをロード Advice やアスペクトメソッドを実行 アスペクトのソース内の pointcut 情報をクライアントに配布 クライアントは、通常のクラスをロードして実行 プログラムの実行時に最初に起動されるのは、アスペクトサーバである。 コンパイラにより変換されたアスペクトのクラスをロードする また、pointcut の情報もアスペクトサーバに読み込まれr、他のホストからの参照に答える準備をしておく SWoPP2003, Matsue
拡張クラスローダ 各クライアント・ホストで、通常のクラスをロードして実行 クラスのロード時 Pointcut をアスペクト・サーバに問い合わせ クラス内の join point が pointcut で指定されていれば、advice を呼び出すコードをbytecode 変換でそこに埋め込む 指定された join point の個所から、遠隔の advice を呼び出すためには、join point 個所に advice を呼び出すコードが差し込まれていなければならない。 SWoPP2003, Matsue
遠隔参照の実装 オブジェクトの遠隔参照を利用して、遠隔メソッド呼び出しを実現 オブジェクトへの参照を遠隔参照に変換 遠隔参照は Remote proxy パターンで実装 オブジェクトへの参照を遠隔参照に変換 指定された join point に制御の流れが到達したとき Aspect.get メソッドによってアスペクトの参照を入手したとき アスペクトメソッドを呼び出すとき 遠隔参照がさすオブジェクトのメソッドを遠隔メソッド呼び出ししたとき Djcutter では、オブジェクトの遠隔参照を利用して、任意のホスト間で遠隔メソッド呼び出しを行うことができる Djcutter が、オブジェクトへの参照を遠隔参照に変換するのは以下の4つ Poincut によって指定された join point に制御の流れが到達したとき SWoPP2003, Matsue
実行時ライブラリの性能測定実験 - Advice 呼び出しと JavaRMI DJcutter は join point が存在するホストの情報等を advice へ送る 同一 ホスト 遠隔 DJcutter 1.3 2.3 JavaRMI (0 引数) 0.7 1.4 (1 引数) 実験に利用したマシンスペック Sun Blade 1000 Sun Enterprise 450 ネットワーク - 1000baseFX 実験では、null の advice を指定した join point 箇所で呼び出した。 また比較のため、JavaRMI の null メソッド呼び出しを測定した Djcutter は join point の情報等を advice へ送るため、JavaRMI のいち引数のメソッド呼び出しと同じ時間がかかることがわかる Null advice/method の実行時間(msec.) SWoPP2003, Matsue
関連研究 分散プログラム内の特定の非機能的な横断的関心事をモジュール化 DJcutter Addistant : オブジェクトの分散配置、遠隔参照の実装 DJcutter AspectJ と同様、汎用的な横断的関心事が扱える 分散している join point を1つのアスペクトの中で取り扱える SWoPP2003, Matsue
まとめ 2 種類の横断的関心事 DJcutter 異なるクラス間 異なるホスト間 Java 用のアスペクト指向言語 AspectJ ではうまくモジュール化しきれない異なるホスト間の横断的関心事をモジュール化する 遠隔ホスト上のプログラム内の join point を指定することが可能な pointcut 機構 分散化した observer パターンに有効 SWoPP2003, Matsue
今後の課題 DJcutter の実行速度を改良 多くの pointcut 機構をサポート Join point が同一ホスト上にある場合も、advice は別プロセスで実行 多くの pointcut 機構をサポート Join point をホストの情報で選択するための指定子は用意していない SWoPP2003, Matsue
SWoPP2003, Matsue
アスペクト記述 グループ図形エディタ内の横断的関心事をモジュール化 アスペクト記述 SWoPP2003, Matsue
SWoPP2003, Matsue
SWoPP2003, Matsue