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