200 likes | 308 Views
Josh : バイトコードレベルでの Java 用 Aspect Weaver. 中川 清志 ( 東工大 ) 立堀 道昭 ( 筑波大 ) 千葉 滋 ( 東工大 ). オブジェクト指向の限界. オブジェクト指向はモジュラリティが優れているが限界もある ある種の処理は複数のオブジェクトに散らばってしまう ログ出力,メモリ管理などの システマティックな処理 その結果保守性が悪化し修正も困難になる. 散らばってしまう例 : ログ出力. class Bike{ void start() { Log.print( “ start ” ); ..
E N D
Josh : バイトコードレベルでのJava用 Aspect Weaver 中川 清志(東工大) 立堀 道昭(筑波大) 千葉 滋 (東工大)
オブジェクト指向の限界 • オブジェクト指向はモジュラリティが優れているが限界もある • ある種の処理は複数のオブジェクトに散らばってしまう • ログ出力,メモリ管理などのシステマティックな処理 • その結果保守性が悪化し修正も困難になる
散らばってしまう例 : ログ出力 class Bike{ void start() { Log.print(“start”); .. } } class Car{ void start() { Log.print(“start”); .. } void back() { Log.print(“back”); .. } } class Log { static void print(String msg) { System.out.println(msg); } } ログ出力をするタイミングを変えるような変更の度に,Car, Bikeクラスのソースコードを修正しなければならない
アスペクト指向 • 散らばっていたコードをアスペクトとしてモジュール化するのがアスペクト指向 • アスペクトはオブジェクトによるモジュール分割を補完するもの • この2種類のモジュールを合成して,1つのプログラムを作り出すことを weaveという weave 実行
AspectJ の新処理系 Josh • AspectJ 言語 • 汎用アスペクト指向言語の代表的なもの • AspectJ 言語の処理系(weaver) • ajc XEROX 版標準処理系 • Josh 我々が新たに開発した処理系
AspectJの言語仕様(1) • Introduction • 既存クラスに新しいメンバを加える • フィールド,メソッドの追加 • 既存クラスの階層構造をかえる • スーパクラス,インタフェースの変更 private int Point.z;public int Point.getZ() { return z; } declare parents : Point implements java.io.Serializable
AspectJの言語仕様(2) • Advice • Join-Point にコード断片を埋め込むように指示 • before, after, aroundの3種類 • Join-Point • プログラム実行の節目 • 例 : メソッド呼び出し,フィールド書き込み etc. before() : call (int Point.getZ()) { System.out.println(“before call getZ()”); } after() : get (int Point.z) { System.out.println(“after get z”); }
標準処理系 ajc の問題点 java source aspect • コンパイル時 weave • 分割コンパイルできない • アスペクトを変更したらソースコードも再コンパイルしなければならない • ソースコードが必要 • サードパーティ製のクラスには使えない • 動的ロードに不向き –プログラム時に利用するクラスがわかっていないといけない weaver ajc weaved source weaved bytecode コンパイラ
本研究の提案 : Josh java source aspect • 問題点に対応した新システムJosh を提案 • ロード時に,バイトコードレベルで weave • 部分コンパイル結果,バイトコードは一旦ローカルディスクに保存 コンパイラ 部分コンパイラ Josh bytecode weaver weaved bytecode
Josh の利点 • バイトコードレベルでのweave の有用性 • 分割コンパイル可能 • アスペクトを変更してもソースの再コンパイルの必要がない • ソースコード無しクラスにも適用できる • ロード時の weave • 複数のアスペクトを切り替えて使える
ソースコードなしクラスのアスペクト • ソースコードを見ないでアスペクトを書けるのか? • 汎用性のあるアスペクトなら書ける • 分散環境への適応 • 既存プログラムとは別に分散化のためのアスペクトを記述し,それらをweave して分散プログラムを生成(e.g. Addistant) • 新しいセキュリティ機構の導入 • セキュリティチェックコードの挿入 基本的にはソースコードのあるプログラムのアスペクトを書く
バイトコードレベルでのweave の制限 • Join-Point の消失 • コンパイル時にソースコードの情報が失われてしまうことがある • 例:インライン展開 • エラーの検出がロード時 • ソースコードレベルならばコンパイルエラーになるものが、バイトコードレベルではロード時エラーになる • 例 : 同じシグネチャのメソッドの追加
Josh の実装 • 部分コンパイラ • アスペクトをバイトコード化する • Josh Weaver • アスペクトとJava バイトコードをweave する
部分コンパイラ (1) • 役割 : ソースコードで存在する,アスペクト内のJavaコード断片をバイトコード化 • ダミークラスにコード断片を埋め込んで通常のJavac でコンパイル • コード断片だけではコンパイルエラーが起こりうる • フィールドやメソッドの参照エラー(上の例では z) int Point.getZ() { return z; } これをバイトコード化したい
部分コンパイラ(2) • バイトコード埋め込み先のクラスの,フィールドやメソッドも書き込む • リフレクションの機能で調査可能 埋め込み先のクラスのフィールド public class Dummy { int z; int getZ() { return z; } } コード断片
Josh Weaver • 役割 : アスペクトのバイトコードをロード時にJavaバイトコードに埋め込む • Javassist が提供する構造リフレクションを使い実装した • プログラムのバイトコードを調べてJoin-Point を見つけ出す • バイトコードを編集してアスペクトのバイトコード断片を埋め込む
javassist.CtClass • 標準JavaリフレクションAPIと同様に,クラス定義を調べるメソッドを提供 • getField(..), getMethod(..),getName(..), getSuperclass(..) • さらにクラス定義を変更するメソッドを提供 • addField(..), addMethod(..), setSuperclass(..), addInterface(..) • Introductionの実現が可能
javassist.CodeConverter • 特定のJoin-Point のバイトコードを変換する • insertBeforeMethod(..) メソッド呼び出しの前に別メソッドを呼ぶ • replaceFieldRead(..) フィールド読み込みを別メソッドに呼び代える • CodeConverter の情報をクラスに反映させてバイトコード変換完了 • Advice の実現が可能
Weaver のオーバヘッドの測定 実行時間 [ミリ秒] USparcIII 750MHzJ2SE 1.3.1 クラスファイルのサイズ [KByte]
まとめ • AspectJ 言語の新コンパイラJosh を提案 • Josh の weave • ロード時 • バイトコードレベル • 分割コンパイル可能 • アスペクト変更による再コンパイルの手間を省ける • ソースコードなしクラスにも適用できる • サードパーティライブラリもOK • 動的ロードにも対応