これはおすすめ 意見交換/共有ツールとその理由

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