1 Software Engineering Laboratory Department of Computer Science
変数の型を考慮したメソッド間の 実行経路の検索 竹之内 啓太,石尾 隆,井上 克郎(大阪大学) 1 Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
研究背景: Reachability Questions プログラムの開発者がデバッグ等を行う際,さまざまな問題に 遭遇する La. Tozaらは開発者が直面する問題の多くはReachability Questionsとして解釈できることを明らかにした † Thomas D. La. Toza and Brad A. Myers. “Developers ask reachability questions. ”, ICSE, pp. 185194, 2010. 2 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
Reachability Questionsはプログラムの実行経路の集合から 特定の条件を満たす実行経路を見つけ出す問題として定義さ れる まず,実行経路の集合を求める必要がある 3 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
Kamiya のアプローチ† • 出力例:get. Instance()を呼び出してからget()を呼び出す実行経路 Show. Week. Day void main(String[]){ Calendar. Util java. util. Calendar get. Day(String){ java. util. Calendar get. Instance() } Calendar. Util java. util. Calendar get. Day. Of. Week(java. util. Calendar){ java. util. Calendar int get(int) } } † Calendarインスタンスを getしてから,曜日をget するまでの実行経路を 知ることができる Toshihiro Kamiya. “An algorithm for keyword search on an execution path. ” , CSMR-WCRE 2014. Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 4
実行不可能な経路 Javaプログラムにおいて実行経路を求める際,メソッド呼び出し を個別に解決すると,実行不能な経路が生じる可能性がある. VTAを用いた 呼び出しの解決の例 list の型の候補 : { Array. List , Linked. List } list. add()の呼び出し候補 • Array. List. add() • Linked. List. add() List<Integer> list; if(i == 0) list = new Array. List<>(); else list = new Linked. List<>(); list. add(3); list. get(0); list. get()の呼び出し候補 • Array. List. get() • Linked. List. get() 5 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
実行不可能な経路 Javaプログラムにおいて実行経路を求める際,メソッド呼び出し を個別に解決すると,実行不能な経路が生じる可能性がある. 4通りの実行経路 list. add() Array. List. add() Linked. List. add() list. get() Array. List. get() Linked. List. get() 実行の流れ 6 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
実行不可能な経路 Javaプログラムにおいて実行経路を求める際,メソッド呼び出し を個別に解決すると,実行不能な経路が生じる可能性がある. 4通りの実行経路 list. add() Array. List. add() Linked. List. add() Array. List. get() Linked. List. get() 2経路は実際は実行不能 list. get() 実行不能経路 7 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
提案手法 • 9 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
説明用サンプルコード Exampleクラスのmainメソッド public static void main(String[] args){ int i = 1; List<Integer> list; if(i == 0) list = new Array. List<>(); else list = new Linked. List<>(); initialize(list); list. size(); } Exampleクラスのinitializeメソッド private static void initialize(List<Integer> list){ list. clear(); list. add(3); } clear()を実行してから, size()が実行されるまで の実行経路を知りたい 以下では,入力の 2つのメソッド名がclear, sizeのときの例を示す 12 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順1: 実行経路の探索起点となる メソッドの特定(1/2) ステップ 1 : 個別にメソッド呼び出しを解決したときのコールグラフの構築 (メソッド呼び出しの解決にはVariable Type Analysis†を使用) Array. List. size Example. main Linked. List. size Example. initialize Array. List. clear Linked. List. clear Array. List. add Linked. List. add † Vijay Sundaresan et al “Practical virtual method call resolution for Java. ”, SIG-PLAN Notice, 2000. Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 13
手順1: 実行経路の探索起点となる メソッドの特定(2/2) ステップ 2 : 入力メソッドclear, sizeに対応する2ノードに対し最も近い共通 の先祖ノード群を特定(本ステップはKamiyaの手法と同様) このメソッドを 「ルートメソッド」と呼ぶ Example. main Array. List. size Linked. List. size Example. initialize Array. List. clear Linked. List. clear Array. List. add Linked. List. add 14 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順1: 実行経路の探索起点となる メソッドの特定(2/2) ステップ 2 : 入力メソッドclear, sizeに対応する2ノードに対し最も近い共通 の先祖ノード群を特定(本ステップはKamiyaの手法と同様) このメソッドを 「ルートメソッド」と呼ぶ Example. main Array. List. size Linked. List. size Example. initialize ルートメソッドはclear, size を呼び出す実行経路の起点となるメソッド Array. List. clear Linked. List. clear Array. List. add Linked. List. add 15 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手続き間実行経路グラフ 次の手順ではオブジェクト変数の型を保持したメソッド呼び出し 関係を手続き間実行経路グラフで表現する 0 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 18 14 16 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手続き間実行経路グラフ 次の手順ではオブジェクト変数の型を保持したメソッド呼び出し 関係を手続き間実行経路グラフで表現する 「エントリーノード」 メソッドの実行に対応 0 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 14 18 「パスノード」 実行経路に対応 17 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手続き間実行経路グラフ 次の手順ではオブジェクト変数の型を保持したメソッド呼び出し 関係を手続き間実行経路グラフで表現する 7: Array. List. clear 0 0 3 1: Example. initialize 1 2: Array. List. size 対応するコード 9 1 8: Array. List. initialize(list); add list. size(); 0 6 1 4: Example. initialize 5: Linked. List. size 16 13 0: Example. main 0 15 12 10: Linked. List. clear 17 1 mainメソッドは 11: Linded. List. 1. Example. initialize add 14 2. Array. List. size というメソッド呼び出しをする実行経路を 持つことを意味する Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 18 18
手続き間実行経路グラフの構築の キーアイデア public static void main(String[] args){ int i = 1; List<Integer> list; if(i == 0) list = new Array. List<>(); else list = new Linked. List<>(); initialize(list); list. size(); } 各経路を抽出 int i = 1; List<Integer> list; list = new Linked. List<>(); initialize(list); list. size(); int i = 1; List<Integer> list; list = new Array. List<>(); initialize(list); list. size(); 経路ごとに型の決定 呼び出し先の確定 0 0 ノードへ変換 1 1 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 21
手順2:手続き間実行経路グラフの構築 実行経路の抽出 ルートメソッドに対応するエントリーノードを作成し,メソッド内の 実行経路を抽出 繰り返し文は同じ地点を高々1度しか通過しないような経路 元のコード 0: Example. main public static void main(String[] args){ int i = 1; List<Integer> list; if(i == 0) list = new Array. List<>(); else list = new Linked. List<>(); initialize(list); list. size(); } 経路を抽出 int i = 1; List<Integer> list; list = new Array. List<>(); initialize(list); list. size(); Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 22
手順2:手続き間実行経路グラフの構築 データフローの解析 ローカル変数・メソッド引数をSSA形式へ変換し 各SSA変数に代入される型をデータフローにより特定 (ローカル変数は宣言部,メソッド引数はエントリーノードの属性) 抽出された経路 int i = 1; List<Integer> list; list = new Array. List<>(); initialize(list); list. size(); 0: Example. main SSA形式へ変換 int i = 1; List<Integer> list 0; list 1 = new Array. List<>(); initialize(list 1); list 1. size(); SSA変数 型 list 0 {} list 1 {Array. List} 23 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順2:手続き間実行経路グラフの構築 SSA変数の型の組み合わせごとに呼び出されるメソッドを特定 thisおよびメソッド引数の型を保持したエントリーノードを作成 (フィールド変数へのメソッド呼び出しはVTAを使用) int i = 1; List<Integer> list 0; list 1 = new Array. List<>(); initialize(list 1); list 1. size(); 1: Example. initialize SSA変数 型 list 0 - list 1 Array. List list 1. size()はArray. List. size()を呼び出す • thisの型 : Array. List • メソッド引数の型 : - 0: Example. main 2: Array. List. size 24 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順2:手続き間実行経路グラフの構築 パスノードを作成し,エントリーノードへ順序付き有向辺を引く int i = 1; List<Integer> list 0; list 1 = new Array. List<>(); initialize(list 1); list 1. size(); 0 0: Example. main 3 1: Example. initialize SSA変数 型 list 0 - list 1 Array. List list 1. size()はArray. List. size()を呼び出す . • thisの型 : Array. List • メソッド引数の型 : - 1 2: Array. List. size 25 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順2:手続き間実行経路グラフの構築 別の実行経路でも同様の処理を行いグラフを構築 元のコード 0 3 1: Example. initialize 1 2: Array. List. size public static void main(String[] args){ int i = 1; List<Integer> list; if(i == 0) list = new Array. List<>(); else list = new Linked. List<>(); initialize(list); list. size(); } 0: Example. main 別の経路を抽出 0 6 1 4: Example. initialize 5: Linked. List. size ノードへ変換 int i = 1; List<Integer> list; list = new Linked. List<>(); initialize(list); list. size(); SSA変数 型 list 0 - list 1 Linked. List Department of Computer Science, Graduate School of Information Science and Technology, Osaka University データフロー解析 26
手順2:手続き間実行経路グラフの構築 新たに作成されたエントリーノードに対して同様の処理を繰り返す 0 0 3 1 1: Example. initialize 9 経路を抽出 1 7: Array. List. clear 8: Array. List. add 2: Array. List. size private static void initialize(List<Integer> list){ 0: Example. list. clear(); main list. add(3); } 4: Example. 0 6 1 initialize listの型はエントリーノードの属性よりArray. List 5: Linked. List. size 27 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順2:手続き間実行経路グラフの構築 すべての呼び出し先のエントリーノードについて同様の処理を 行っていくことでグラフの構築を完了 0 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 18 14 28 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順3:手続き間実行経路グラフからの メソッド列の抽出 入力メソッド名clear, sizeに対応するエントリーノードの全組み合 わせを求める clearに対応 組み合わせは (7, 2), (7, 5), (10, 2), (10, 5) 0 3 0 1: Example. initialize 9 1 2: Array. List. size 0: Example. main 0 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 13 sizeに対応 6 1 7: Array. List. clearに対応 0 12 1 10: Linked. List. clear 11: Linded. List. add 17 18 14 sizeに対応 30 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順3:手続き間実行経路グラフからの メソッド列の抽出 各組み合わせに対し,その先祖ノードの集合を求める (Array. List. clear, Array. List. size)の組み合わせでは以下のよう になる 0 (7, 2)の組み合わせ 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 18 14 31 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順3:手続き間実行経路グラフからの メソッド列の抽出 先祖ノードの集合に含まれるパスノードとその子から構成され る部分グラフを求める (入力メソッドと関係が弱い経路の排除) (7, 2)の組み合わせ 0 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 18 14 32 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順3:手続き間実行経路グラフからの メソッド列の抽出 先祖ノードの集合に含まれるパスノードとその子から構成され る部分グラフを求める (入力メソッドと関係が弱い経路の排除) (7, 2)の組み合わせ 0 0 3 1: Example. initialize 9 1 1 2: Array. List. size 0 6 1 4: Example. initialize 5: Linked. List. size 15 8: Array. List. add 16 10: Linked. List. clear 17 13 0: Example. main 0 7: Array. List. clear 12 1 11: Linded. List. add 18 14 33 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
手順3:手続き間実行経路グラフからの メソッド列の抽出 各エントリーノードがひとつのパスノードを持つような組み合わ せが実行経路に対応.提示するメソッド列はArray. List. clearを 実行してからArray. List. sizeを実行する部分のみ (7, 2)の組み合わせ 0 0 3 1: Example. initialize 1 9 1 7: Array. List. clear 8: Array. List. add 2: Array. List. size 0: Example. main 提示するメソッド列 Example. main(){ Example. initialize(){ Array. List. clear() Array. List. add() } Array. List. size() } Department of Computer Science, Graduate School of Information Science and Technology, Osaka University listの型が Array. Listのとき の実行経路 34
手順3:手続き間実行経路グラフからの メソッド列の抽出 (Array. List. clear, Linked. List. size)では,各エントリーノードにひ とつのパスノードを対応させたときclearを実行してからsizeを実 行する経路が存在しない (7, 5)の組み合わせの 部分グラフ 0 1: Example. 0 0 0 3 1: Example. initialize 2: Array. List. size 9 1 0 6 initialize 1 2 1 1 5: Linked. List. size 1 9 10: Linked. List. clear 8: Array. List. add 1 6 1 3 0: Examp le. main 1 6 実行可能な経路 は存在しない 1 7 0: Examp le. main 11: Linded. List. add 1 5 1 1 3 0: Examp le. main 4: Example. 3 2: Array. List. size 8: Array. List. add 1 0 7: Array. List. clear 1 5 initialize 7: Array. List. clear 0 1 8 4: Example. 0 1 4 6 initialize 1 2 1 1 5: Linked. List. size Department of Computer Science, Graduate School of Information Science and Technology, Osaka University 1 4 10: Linked. List. clear 1 7 11: Linded. List. add 1 8 35
手順3:手続き間実行経路グラフからの メソッド列の抽出 結果としてサンプルコードの場合では 2つのメソッド列が提示される . これらの経路はオブジェクト変数の型が考慮された実行経路に対 応している (Array. List. clear,Array. List. add) の組み合わせ Example. main(){ Example. initialize(){ Array. List. clear() Array. List. add() } Array. List. size() } (Linked. List. clear,Linked. List. add) の組み合わせ Example. main(){ Example. initialize(){ Linked. List. clear() Linked. List. add() } Linked. List. size() } 36 Department of Computer Science, Graduate School of Information Science and Technology, Osaka University
- Slides: 43