アスペクト指向言語による 例外処理の記述方法の改善

Slides:



Advertisements
Similar presentations
Web アプリをユーザー毎に カスタマイズ可能にする AOP フレームワーク
Advertisements

コンパイラ 2011年11月14日
実行時のメモリ構造(1) Jasminの基礎とフレーム内動作
プログラミング基礎I(再) 山元進.
Myoungkyu Song and Eli Tilevich 発表者: 石尾 隆(大阪大学)
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
通信処理のカーネル内競合を 検出するアスペクト指向 カーネルレベルロガー
福盛 秀雄, 浜中 征志郎, 菅原 健一, 吉川 潤, 中山 周平 早稲田大学 村岡研究室
例外,並行・同期処理,ゴミ集め 2002年7月7日 海谷 治彦.
AspectScope によるアスペクトとクラスのつながりの視覚化
同期的にアドバイスを活性化できる分散動的アスペクト指向システム
ユーザ毎にカスタマイズ可能な Web アプリケーション用のフレームワークの実装
アスペクト指向プログラミングを用いたIDSオフロード
アスペクト指向プログラミングと Dependency Injection の融合
遠隔ポイントカット - 分散アスペクト指向プログラミング のための言語機構
J2EEアプリケーションにおける アプリケーションレベルスケジューリング
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
8.1 例外処理 8.2 catchブロックの検索 8.3 throwステートメント 8.4 例外とエラークラス 8.6 独自の例外
プログラミング言語入門 手続き型言語としてのJava
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
ソードコードの編集に基づいた コードクローンの分類とその分析システム
独習Java ・ 8.1  例外処理 ・ 8.2  catch ブロックの検索  12月 5日    小笠原 一恵.
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
リファレンスの復習と例外処理 2005年6月14日 海谷 治彦.
暗黙的に型付けされる構造体の Java言語への導入
理学部 情報科学科 指導教官 千葉 滋 助教授 学籍番号 03_03686 内河 綾
統合開発環境のための アスペクト指向システム
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
Java Bytecode Modification and Applet Security
ユーザ毎にカスタマイズ可能な Webアプリケーションの 効率の良い実装方法
10-1 SAXの概要 10-2 Saxプログラミングの基礎 10-3 saxのプログラム例
動的データ依存関係解析を用いた Javaプログラムスライス手法
既存Javaプログラム向け 分散化支援システムの開発
豊富な情報を基にした pointcut を記述できるアスペクト指向言語
Recoveryアドバイスをもつ アスペクト指向システム
ソフトウェア制作論 平成30年11月21日.
アスペクト指向言語のための 独立性の高いパッケージシステム
バイトコードを単位とするJavaスライスシステムの試作
J2EEアプリケーションにおける アプリケーションレベルスケジューリング
pointcut に関して高い記述力を持つ アスペクト指向言語 Josh
new Calc(7,3).divInt()実行前
ソフトウェア保守のための コードクローン情報検索ツール
Java における 先進的リフレクション技術
Javaバーチャルマシンを利用した 動的依存関係解析手法の提案
プログラムの織り込み関係を可視化するアウトラインビューの提案と実装
JAVAバイトコードにおける データ依存解析手法の提案と実装
アルゴリズムとデータ構造演習(7月1日) 例外処理 2019/5/8.
静的情報と動的情報を用いた Javaプログラムスライス計算法
分散 Java プログラムのための アスペクト指向言語
Josh : バイトコードレベルでのJava用 Aspect Weaver
統合開発環境によって表現された 言語機構によるコードのモジュール化
同期処理のモジュール化を 可能にする アスペクト指向言語
プログラムの差分記述を 容易に行うための レイヤー機構付きIDEの提案
オープンソースソフトウェアに対する コーディングパターン分析の適用
ユビキタスコンピューティングの ための ハンドオーバー機能付きRMIの実装
状況に応じて適切な 例外処理が行なえる アスペクト指向分散環境実験の 支援ツール
プログラム分散化のための アスペクト指向言語
統合開発環境のための プログラミング言語拡張 フレームワーク
開発者との対話を活かした 横断的構造の表現
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
プログラムの一時停止時に 将来の実行情報を提供するデバッガ
回帰テストにおける実行系列の差分の効率的な検出手法
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
プログラミング演習I 2003年6月11日(第9回) 木村巌.
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
GluonJ を用いたビジネスロジックからのデータベースアクセスの分離
ソケットの拡張によるJava用分散ミドルウエアの高信頼化
第6章 インターネットアプリケーション 6.1 インターネットアプリケーション 6.2 Javaによるネットワーク処理 6.3 電子メール
Josh : バイトコードレベルでのJava用 Aspect Weaver
Presentation transcript:

アスペクト指向言語による 例外処理の記述方法の改善 数理・計算科学専攻 千葉研究室 熊原奈津子 指導教員:千葉滋

例外処理の分離の重要性 例外処理とは ロジックとは分離して 書くべき 異常時の処理をまとめて記述したもの 正常時には実行されないコード Javaにはtry-catchがある 分離はできるが正常時の処理のすぐ下に書かなければならない try { //ファイルへの操作 File file = new File(); file.open(); file.read(); file.write(); : } catch(IOException e){ IOException が発生した 場合の例外処理内容 } 修士論文発表会

頻繁に例外処理を差し替えたい - 実験プログラム 頻繁に例外処理を差し替えたい   - 実験プログラム 分散環境で動くサーバの性能をテスト 最初は小規模なので例外処理なし 問題(故障)が起きたら必要に応じて追加 故障 命令 コンソール マシンの絵 命令 負荷 コンソールマシン 命令 負荷 制御 プログラム サーバマシン クライアントマシン 修士論文発表会

元のプログラムを編集 class Sender{ public void sendCommand(String host, String command) throws Exception{   :   Socket s = new Socket(host, port);   DataOutputStream out   = new DataOutputStream(s.getOutputStream());   out.write(command);   out.close();   s.close();       System.out.println(command + “ has been sent to ” + host); } try{ } catch(SocketException e){ // 故障を見つけたらログを出力 } クライアントに ソケットを張る 命令を 送信 複数のホストに 命令を送信 for (int i = 0; i < hostName.length; i++){   new Sender().sendCommand(hostName[i], “./client.sh”); } 修士論文発表会

他のマシンを使って再試行(リカバリ) catch 節の中から try ブロックの先頭へ戻る ホスト故障時には、自動的に復旧処理 try{   Socket s = new Socket(host, port);   DataOutputStream out = new DataOutputStream(    s.getOutputStream());   out.write(command);    out.close();   s.close(); } catch(SocketException e) {  ホストを変更して再試行 } Java には再試行を直接実現する 構文はない 修士論文発表会

GluonJ/Rの提案 - Recover アドバイスをもつ AOP System 例外処理をアスペクトとして記述 例外処理を分離 もとのロジックを壊さずに追加・削除が可能 例外処理に特化した pointcut 指定子を提供 Java バイトコード変換で実現 再試行するための特殊メソッド(retry)を用意 アドバイス内で利用可能 リカバリ処理を容易に記述できる 修士論文発表会

GluonJ/Rの特徴:アスペクトとして分離 block ポイントカット指定子 範囲をポイントカットできる ジョインポイントのペアを指定(try ブロック指定に相当) recover アドバイス catch 節に相当 @Glue class SenderRecovery { @Recover( etype = “SocketException”, advice = “{ $1 = getAnotherHost(); GluonJR.retry(); }”) Pointcut p = Pcd .block(Pcd.call(“Socket#new(..)”), Pcd.call(“PrintStream#plintln()”));} Socket s = new Socket( host, port); DataOutputStream out = newDataOutputStream( s.getOutputStream()); out.write(command); out.close(); s.close(); System.out.println(“done”); アスペクトの単純な例と、適用されるプログラムの例 アスペクトで記述することにより、 もとのロジックを壊さず、例外処理を分離 分離して記述 修士論文発表会 元のプログラム アスペクト

GluonJ/R のプログラム例 @Glue class SenderRecovery { @Refine static class Diff extends Sender{ public String getAnotherHost(){ // 他のホスト名を返す } @Recover( etype = “SocketException”, advice = “{ $1 = getAnotherHost(); GluonJR.retry(); }”) Pointcut p = Pcd.block( Pcd.call(“Socket#new(..)”), Pcd.call(“PrintStream#plintln()”)) アドバイス 例外処理を 追加したい 範囲を指定 修士論文発表会 ウィーブ

GluonJ/Rの特徴:再試行 特殊メソッド GluonJR.retry() アドバイスの中で利用可能 block で指定した範囲の先頭に戻る @Glue class SenderRecovery { @Recover( etype = “SocketException”, advice = “{ $1 = getAnotherHost(); GluonJR.retry(); }”) Pointcut p = Pcd .block(Pcd.call(“Socket#new(..)”), Pcd.call(“PrintStream#println()”));} Socket s = new Socket(host, port); DataOutputStream out = newDataOutputStream( s.getOutputStream()); out.write(command); out.close(); s.close(); System.out.println(“done”); アスペクトの単純な例と、適用されるプログラムの例を載せる (先のスライドの例をそのまま載せるのが望ましい) リトライしやすい 元のプログラム アスペクト 修士論文発表会

行アノテーション ジョインポイントの一種 if(・・・){ : } else { GluonJ/Rの文法拡張 @Line(begin) for(・・; ・・; ・・){ @Line(end) ジョインポイントの一種 GluonJ/Rの文法拡張 block による範囲指定に利用 将来指定されそうな場所にジョインポイントがないとき、あらかじめ書いておく 自由に名前がつけられる 自由に名前がつけれる Pointcut p = Pcd.block(Pcd.line(“begin”), Pcd.line(“end”)); 行あのてーしょんは、ポイントカットできる 修士論文発表会

GluonJ/R の実装 GluonJ 1.3 を拡張して実装 行アノテーションのプリプロセッサを用意 プラグイン同様、追加削除が容易 GluonJ の総コード数5000行に対して 拡張部分は400行程度 バイトコード変換には Javassist を利用 行アノテーションのプリプロセッサを用意 修士論文発表会

例外ハンドラの追加 メソッドを実装している バイトコード ユーザから与えられる情報 始点・終点(ソースコード) ←始点 処理したい例外の型 例外が生じた場合に 実行したいコード ←始点 クラスファイル block で指定した範囲 ←終点 ・・・ メソッドの情報 ←例外ハンドラの先頭 アドバイス メソッドの属性 Exception Table に含まれる情報 Exception Table ・・・ 例外ハンドラがアクティブとなる バイトコードの範囲(始点・終点) 例外ハンドラがキャッチする 例外のクラス 例外ハンドラの先頭 ・・ 範囲・例外の種類・飛び先 修士論文発表会

GluonJR.retry() の実装 GluonJ/R 内でソースコードをコンパイルし、バイトコードへ変換 invokestatic 命令を命令長が同じ3バイトのgoto 命令に置換 メソッドの バイトコード ←始点 block 範囲の 始点に戻る アドバイス   : GluonJR.retry();   :  invokestatic   :  goto コンパイル 変換 修士論文発表会

範囲を選択するアルゴリズム 始点・終点が同一メソッド内に存在 最も近いペア(始点・終点)を選択 Pointcut p = Pcd.block( Pcd.call(“foo(..)”), Pcd.call(“bar(..)”)); 始点・終点が同一メソッド内に存在 最も近いペア(始点・終点)を選択 始点となるソースコードが実行される直前から終点となるソースコードが実行される直前までを選択 始点候補 終点候補 foo(); : hoge(); bar(); block 修士論文発表会 if (終点に一致 && 始点候補が存在 && 両者が同一メソッド内に存在){ このペアを範囲として選択; } if (始点に一致){ ジョインポイントを上書き保存;

実装の要点: blockで指定する範囲の始点 ジョインポイント・シャドーではない ジョインポイントに直接対応するバイトコード命令ではない Invokevirtual, getfield 等 その命令を含むソースコード行の最初のバイトコード命令 retry() の実現のため アドバイス内から goto で戻っても bytecode verifier をパスする new Socket dup aload_1 iload 4 invokespecial Socket() astore 5 先頭の命令 Socket s = new Socket(host, port); コンパイル Try ブロックの始点と終点には、スタックが空の状態で実行される命令の直前が選択される。 これは、recovery アドバイス内で記述できる retry() を実現するためである。 GluonJR での retry() は、bytecode 変換により、try ブロックの始点への goto 命令に置き換えられている。 もし try ブロックの始点のスタックの状態が空でなかった場合、 Retry() の直後に、スタック上にオペランドが積まれていることを想定した命令が実行されてしまう。 Retry() の実行後は、スタックの状態は空であるはずなので、 ここでスタックの整合性が保たれず、 Verify error が起きてしまう。 JP Shadow 修士論文発表会

× JVMのスタックの状態遷移図 ○ ・・・・・ 例 Socket s = new Socket(host, port); コンパイル new Socket dup aload_1 iload 4 invokespecial Socket() astore 5 Socket s = new Socket(host, port); コンパイル new dup ・・・・・ int invokespecial str スタックは 空の状態 ref ref ref ref ref × ○ retry() で戻ってくる 修士論文発表会

行アノテーションのプリプロセッサ プリプロセッサで空の スタティックメソッド呼び出しに変換 if(・・・){ : } else { プログラムの挙動には影響なし 性能に対する影響については後述 if(・・・){ : } else { } @Line(begin) for(・・; ・・; ・・){ @Line(end) LineAnnotation.begin(); class LineAnnotation{ public static void begin(){} public static void end(){} } LineAnnotation.end(); 修士論文発表会

現在の実装の限界 異なるブロックをまたぐ範囲の選択 finally 節の扱い メソッドをまたぐ範囲は選択できない for、while 文等のブロックをまたいでも選択可能 finally 節の扱い 選択範囲外の finally 節が範囲に含まれてしまう可能性がある(コンパイラによる) Recover アドバイス内で例外を投げると、元の finally 節が無視される 修士論文発表会

finally 節に関する問題 例1 例2 try { : if (・・){ return; } } catch (){ 例3 try { : } catch (){ } finally { } try { : } catch (){ } finally { } 例外発生 アドバイス    throw e; アドバイス    追加した方の優先順位が 高いため finally 節が 実行されない 展開された finally 節も 含んでしまう finally 節が実行されない 修士論文発表会

実験について 実験環境 目的 CPU : Intel Pentium 4 CPU 2.8GHz メモリ : 1GB OS : Microsoft Windows XP Professional SP2 JVM バージョン : 1.5.0_06 目的 GluonJ/Rで例外処理をアスペクトとして追加した場合のオーバーヘッドを測定 修士論文発表会

実験:try-catch文との実行速度の比較 メソッド m() を10億回 try-catch文を追加 アスペクトをウィーブ public class Test { public void m() throws Exception{ a(); b(); } public void a() throws Exception{} public void b() {} try{ } catch(Exception e){} 実行時間(秒) 例外処理なし 2.6 try-catch文 17.0 GluonJ/R @Glue class InsertTryCatch { @Recover(etype = "java.lang.Exception", advice = "") Pointcut p = Pcd.block(Pcd.call("test.Test#a(..)"), Pcd.call("test.Test#b(..)")); } 修士論文発表会

実験:行アノテーションの性能実験 実行時間(秒) 行アノテーションなし 2.6 行アノテーション追加(例外処理なし) public class Test { public void m() throws Exception{ @Line(begin) a(); @Line(end) b(); } public void a() throws Exception{} public void b() {} 実行時間(秒) 行アノテーションなし 2.6 行アノテーション追加(例外処理なし) 行アノテーション追加(例外処理追加) 17.1 @Glue class InsertTryCatch { @Recover(etype = "java.lang.Exception", advice = "") Pointcut p = Pcd.block(Pcd.line("begin"), Pcd.line("end")); } 修士論文発表会

AspectJ との比較 handler ポイントカット after throwing アドバイス 既に try-catch 文がプログラムに含まれている場合、 catch 節の実行時をジョインポイントとして選択 after throwing アドバイス 選択されたジョインポイントが例外を投げて異常終了した場合に実行される 例外を補足する範囲の粒度がメソッドボディ Java の throws も同様の問題 リカバリ処理の実装には使えない 最後に必ず例外を投げなければならない Handler は、try-catch が含まれていない場合に、無力 Javaのthrowsを使って、wrapper をしかけても、粒度がメソッド本体 修士論文発表会

関連研究 Eiffel や Ruby の retry 機構 範囲を選択するポイントカット Java には存在しなかった ループ処理のためのジョインポイント [Harbulot ら ‘06] for 文等のブロック全体をポイントカット ポイントカットできないループも数多く存在 block ポイントカットと行アノテーションは 任意の範囲を選択可能 修士論文発表会

まとめ・今後の課題 GluonJ/R 今後の課題 例外処理をロジックと分離して記述可能 容易にリカバリできる オーバーヘッドはほとんどなし 範囲をポイントカットできる pointcut 指定子 容易にリカバリできる アドバイスの中で再試行可能なメソッド オーバーヘッドはほとんどなし 今後の課題 現実のアプリケーションに適用 うまく記述できるか コードサイズをどのくらい減らすことができるか 修士論文発表会