1 Reserved member 方式による メンバーの実行時追加機構の提案 10M37172 早船 総一郎 指導教員 千葉 滋 2 実行中にプログラムを差し替える • 対話的開発 ▫ ▫ ▫ ▫ ▫ 開発中のプログラム ブレークポイントで一時停止 コードの修正 (送り込む) 再開 デバッグ モード 追加 古いコー ド 書き換え 新しいコー ド 3 実行中にプログラムを差し替える • 対話的開発 ▫ ▫ ▫ ▫ ▫ 開発中のプログラム ブレークポイントで一時停止 コードの修正 (送り込む) 再開 デバッグ モード 追加 古いコー ド 書き換え 新しいコー ド 4 HotSwap で行える実行時のコード変更 • Java 仮想機械の標準機能 • 可能な修正: メソッドボディの変更のみ • メンバーの追加は不可 class Position { ▫ シグネチャの変更も不可 void move(int i){ x = x + i; } class Main{ void action (Position p) { p.move(1); }} 書き換え class Main { void action (Position p) { double d = p.distance(0,0); }} 追加 } class Position { void move(int i){x = x + i;} double distance(int i,int j){ double d2 = Math.pow(x – i, 2) + Math.pow(y – j, 2); double d = Math.sqrt(d2); return d; }} 5 提案:Reserved member 方式 • 実行中にメンバーの追加を可能に ▫ 実行前に予備のメンバーを準備 ▫ 追加時に予備のメンバーを変更し、追加のメンバーを実現 システム上 ユーザーの記述 クラス 準備 クラス Reserved member 6 提案:Reserved member 方式 • 実行中にメンバーの追加を可能に ▫ 実行前に予備のメンバーを準備 ▫ 追加時に予備のメンバーを変更し、追加のメンバーを実現 システム上 ユーザーの記述 クラス クラス Reserved member 追加メンバー 追加メンバー の内容 7 ユーザーが行いたいこと class Main{ void action (Position p) { p.move(1); }} class Position { void move(int i){x = x + i;} } class Main { void action (Position p) { double d = p.distance(0,0); }} class Position { void move(int i){x = x + i;} double distance(int i,int j){ /* distance */ } } 8 システム上では class Main{ void action (Position p) { p.move(1); }} class Position { void move(int i){x = x + i;} } class Position { void move(int i){x = x + i;} reserved$ (…){ 準備 } } class Main { void action (Position p) { double d = p.distance(0,0); }} 呼び出し class Main{ void action(Position p) { double d = class Position { void move(int i){x = x + i;} double distance(int i,int j){ /* distance */ } } class Position { void move(int i){x = x + i;} reserved$ の呼び出し }} reserved$ (…){/* distance */} } 変更 9 Reserved member • 実行中にメンバーを追加するときに変更 ▫ ロード時にバイトコードを変換して追加(標準機能で可能) • Reserved method ▫ 戻り値の型は Object 引数の型は Object の配列と String class Position { void move(int i){x = x + i;} } 実行前に 追加 class Position { void move(int i){x = x + i;} 準備 public Object reserved$ (Object[] objects, String key) { return null; } } 10 呼び出し側の変換 • 追加したメソッドは実際には存在しない ▫ Reserved method を呼び出すように変換 型変換を行い、引数と戻り値を適切に扱う class Main { void action (Position p) { double d = p.distance(0,0); }} 呼び出し class Main{ void action(Position p) { double d = (double) p.reserved$( new Object[] {0, 0}, “distance(I,I)D”); class Position { void move(int i){x = x + i;} reserved$ の呼び出し }} reserved$ (…){ } } 11 Reserved method を変更して実現 • 追加するメソッドの中身を reserved method にコピー • 実行時に型変換するコードを挿入 public Object reserved$(Object[] objects, String key) { 型変換するコード Object[] → int, int double → Object /* distance */ } class Position { void move(int i){x = x + i;} double distance(int i,int j){ /* distance */ } } 変更 class Position { void move(int i){x = x + i;} reserved$ (…){/* distance */} } 12 型変換 : 引数と戻り値 • Object 型の配列から値を取り出し、適切な型に ▫ 引数で利用しなかった変数は局所変数が利用 • 戻り値はボクシング p.reserved$(new Object[] {0, 0}, “distance(I,I)D”); Object[] String int int double double d2 = Math.pow(x – i, 2) + Math.pow(y – j, 2); double d = Math.sqrt(d2); return d; double 13 複数のメンバーの追加 • 一つの reserved method が複数のメソッドを実現 システム上 • 追加されたメソッドの切替 ▫ メソッドのシグネチャを利用 reserved$ (Object[] objects, String key){ if(key.equals(“distance(I,I)D”)){ ユーザーの記述 } class Position{ 追加メンバー distance 型変換 distance if(key.equals(“move(I,I)V”)){ 追加メンバー move } 追加メンバー setX 型変換 move if(key.equals(“setX(I)V”)){ } } } 型変換 setX 14 オーバーライドの考慮 システム上 Data • 既に定義されている場合 ▫ 他のクラスも変更が必要 ▫ ユーザーの記述と システム上のコードを すり合わせる ① action(new Position()); ② action(new Circle()); ③ action(new Data()); action (Data d) { d.distance(0,0); } どれを? + distance(int, int) : double + reserved$(Object[], String) : Object Position + reserved$(Object[], String) : Object Circle + reserved$(Object[], String) : Object 15 オーバーライドの考慮 システム上 Data • 既に定義されている場合 ▫ 他のクラスも変更が必要 ▫ ユーザーの記述と メソッド システム上のコードを distance の追加で利用 すり合わせる ① action(new Position()); ② action(new Circle()); ③ action(new Data()); action (Data d) { reserved$ の呼び出し } どれを? + distance(int, int) : double + reserved$(Object[], String) : Object Position + reserved$(Object[], String) : Object Circle + reserved$(Object[], String) : Object 16 オーバーライドの対応 システム上 Data • Reserved method で 継承関係を実現 distance を コピー ▫ オリジナルがある場合は コピー ▫ オリジナルがない場合は 親を呼ぶ ① action(new Position()); ② action(new Circle()); ③ action(new Data()); action (Data d) { reserved$ の呼び出し } どれを? + distance(int, int) : double + reserved$(Object[], String) : Object distance の追加 で利用 Position + reserved$(Object[], String) : Object 親の reserved $ を 呼び出す Circle + reserved$(Object[], String) : Object 17 応用例:サービスを止めずに開発 • プログラムの再起動を行わずに ▫ セキュリティパッチを適用 ▫ 性能を調査 システム 変更 新しいバイトコード 更新 古いバイトコー ド 18 実験 • SPECjvm2008を利用、マイクロベンチマークを作成利用 することで、以下のオーバーヘッドを計測 ▫ Reserved member の準備 ▫ 実行中のプログラムの監視機能 ▫ 型変換を必要とするメソッド呼び出しのオーバーヘッド • 実験環境 ▫ OS: WindowsXP ▫ CPU: Intel Core2Duo 1.83 GHz ▫ メモリ: 1.5 GB 19 Reserved member の準備 clas s Main { public static void main ( String [ ] args ) { // warmup // n 回ロードを行う new A0 ( ) ; new A1 ( ) ; … new An-1( ) ; // m回ロードを行う long start = System . currentTimeMillis ( ) ; new An ( ) ; new An+1( ) ; … new An+m-1( ) ; long end = System . currentTimeMillis ( ) ; System . out . println ( end - start ) ; }} 20 実験:Reserved member の準備 • Reserved member 一つあたり、約 0.3ms • 実行中のプログラムの監視機能は、約 37% クラス1つあたりのロード時間 (マイクロ秒) 4000 3500 3000 2500 2000 1500 1000 500 0 利用して いない 0 5 (Reserved member 数) 10 15 21 Reserved method で実現されたメソッド • 呼び出し回数の多いメソッドを reserved method に変換 • その実行時間を計測 class Position { class Main { void action (Position p) { double d = p.distance(0,0); }} void move(int i){x = x + i;} double distance(int i,int j){ /* distance */ } 比 較 } class Position { void move(int i){x = x + i;} reserved$ (…){ class Main{ void action(Position p) { double d = reserved$ の呼び出し }} if(key.equals(“distance(I,I)D”)){ } } } 型変換 distance 22 呼び出し回数の多いメソッド • SPECjvm2008 の中の XML 中の メソッド呼び出しの回数 isDosNewLine class ExOutputStream { Object reserved$ (Object[] objects, String key){ if(key.equals(“isDosNewLine([BI)Z”)){ 型変換 isDosNewLine } if(key.equals(“isUnixNewLine([BI)Z”)){ 型変換 isUnixNewLine } } } isUnixNewLine 23 実験:型変換を必要とするメソッド呼び出し のオーバーヘッド(結果) • 上位 2 つを reserved method に実現、呼び出す • 型変換のオーバーヘッドは約 0.8% 22 21 20 (ops/m) 19 18 default 17 reserved に変換 16 15 14 1 2 3 4 5 6 iteration 7 8 9 10 24 関連研究 • Dynamic Virtual Machine [‘00 Malabarba ら] ▫ 改造した Java 仮想機械上で変更を行う機構 ▫ 特別なクラスとクラスローダーを定義 ▫ 一般的に利用されている標準 Java 仮想機械を用いた上 で実現する方法が望ましい • Envelope-Based weaving [‘05 Bockisch ら] ▫ 事前にメンバーを準備しておく手法 ▫ Aspect 指向言語の織り込みを支援 ▫ クラス定義の変更には対応していない 25 まとめ • 実行中にメンバーの追加を行う機構を提案 ▫ 実行前に予備のメンバーを準備 ▫ 追加時に予備のメンバーを変更して、追加のメンバーを実現 • 実験 ▫ マイクロベンチマーク、SPECjvm2008 を利用 ▫ オーバーヘッド:準備時は大きいが、実行中はごく小さい • 今までの活動 ▫ 情報処理学会論文誌 プログラミング (投稿中) ▫ 口頭発表 : PPL’11 標準 Java 仮想機械上で動的にメンバーの追加を行う機構の 提案 ▫ ポスター : PPL’10
© Copyright 2025 ExpyDoc