計算機言語システム論 10/02 論文サーベイ 吉野 寿宏 (米澤研究室 D1).

Slides:



Advertisements
Similar presentations
独習JAVA Chapter 6 6.6 クラスの修飾子 6.7 変数の修飾子 結城 隆. 6.6 クラスの修飾 abstract インスタンス化できないクラス。1つまたは複数のサブクラスで 実装してはじめてインスタンス化できる。 final 継承されたくないことを明示する。これ以上機能拡張 / 変更でき.
Advertisements

6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
スレッドの同期と、スレッドの使用例 スレッドの同期 Lockオブジェクト: lockオブジェクトの生成
アルゴリズムとプログラミング (Algorithms and Programming)
Myoungkyu Song and Eli Tilevich 発表者: 石尾 隆(大阪大学)
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
仮想マシンの並列処理性能に対するCPU割り当ての影響の評価
アルゴリズムとデータ構造 2011年6月13日
F11: Analysis III (このセッションは論文2本です)
2007/1/11 山下 諒蔵 佐藤 春旗 前田 俊行 大山 恵弘 佐藤 秀明 住井 英二郎
リファクタリングのための 変更波及解析を利用した テスト支援ツールの提案
第20章 Flyweight ~同じものを共有して無駄をなくす~
メソッド名とその周辺の識別子の 相関ルールに基づくメソッド名変更支援手法
動的スライスを用いたバグ修正前後の実行系列の差分検出手法の提案
プログラム静的解析手法の効率化と 解析フレームワークの構築に関する研究
Solving Shape-Analysis Problems in Languages with Destructive Updating
プログラム実行履歴を用いたトランザクションファンクション抽出手法
型付きアセンブリ言語を用いた安全なカーネル拡張
静的情報と動的情報を用いた プログラムスライス計算法
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
動的スライスを用いた バグ修正前後の実行系列の比較
暗黙的に型付けされる構造体の Java言語への導入
ポインタ解析におけるライブラリの スタブコードへの置換の効果
オブジェクト指向プログラムにおける エイリアス解析手法の提案と実現
オブジェクト指向プログラムにおける エイリアス解析について
動的スライスを用いたバグ修正前後の実行系列の差分検出手法
Javaプログラムの変更を支援する 影響波及解析システム
動的データ依存関係解析を用いた Javaプログラムスライス手法
Java8について 2014/03/07.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
コードクローン検出に基づくデザイン パターン適用支援手法の提案と実現
プログラム理解におけるThin sliceの 統計的調査による有用性評価
アルゴリズムとデータ構造 2010年7月26日
pointcut に関して高い記述力を持つ アスペクト指向言語 Josh
オブジェクト指向プログラミングと開発環境
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造1 2006年7月11日
インスタンスの型を考慮したJavaプログラムの実行経路の列挙手法の提案
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
オブジェクト指向 プログラミング 第六回 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
同期処理のモジュール化を 可能にする アスペクト指向言語
C#プログラミング実習 第3回.
プログラムスライスを用いた凝集度メトリクスに基づく 類似メソッド集約候補の順位付け手法
設計情報の再利用を目的とした UML図の自動推薦ツール
アルゴリズムとデータ構造 2012年6月11日
アルゴリズムとデータ構造1 2008年7月24日
サブゼミ第7回 実装編① オブジェクト型とキャスト.
アルゴリズムとデータ構造1 2009年6月15日
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
発表者: 稲葉 一浩 複雑ネットワーク・地図グラフ セミナー 2017/1/19
JAVA入門⑥ クラスとインスタンス.
18. Case Study : Imperative Objects
SMP/マルチコアに対応した 型付きアセンブリ言語
エイリアス関係を考慮した Javaプログラム用静的スライシングツール
動的スライスを用いたバグ修正前後の実行系列の差分検出手法の提案
動的スライスを用いたバグ修正前後の実行系列の差分検出手法の提案
アルゴリズムとデータ構造 2010年6月17日
コードクローン解析に基づく デザインパターン適用候補の検出手法
回帰テストにおける実行系列の差分の効率的な検出手法
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
全体ミーティング(9/15) 村田雅之.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
Presentation transcript:

計算機言語システム論 10/02 論文サーベイ 吉野 寿宏 (米澤研究室 D1)

今回の論文 M. Naik, A. Aiken, J. Whaley. Effective Static Race Detection for Java. PLDI ’06. Race detection を行うシステム Chord を実装した http://www.stanford.edu/~mhn/chord.html にて入手可 Chord を用いて実際のアプリケーションの race condition を発見し、バグの修正につながった

背景: Race Detection Race (競合) とは何か? Race はバグの元である マルチスレッドのプログラムが同一のメモリ領域に対して同時に(同期なしに)参照を行うこと しかも少なくとも一つが書き込みアクセスである ような場合 Race はバグの元である プログラムの invariant (常に成り立っているべき 条件)を壊すおそれがある スケジューリングなどの状況により発生し、再現が難しい

2 スレッドがConnection を持ってしまう! An Example of Race JdbF からの例 public class ConnectionSource { private Connection conn; private boolean used;    public Connection getConnection() throws SQLException { if (!used) { used = true; return conn; } throw new SQLException(...); }; ロックをかけていない スレッド 1    2 2 スレッドがConnection を持ってしまう!

既存研究 (1) 動的な検出 既存研究の多くはほとんどこちらの手法 Happens-before relation[L. Lamport 1978] 時間順に起こらなければならない制約を表す半順序 False negative が非常に多い(検出精度が悪い) Lockset algorithm スレッドの保持しているロックを動的に管理 lock/unlock 以外の同期手法を使うと false positive が出る

既存研究 (2) 静的な検出 本論文はこちらの手法に分類される 型検査器によるシステム モデル検査器によるシステム 同期に関する挙動を型などで表す方式 しかし型を自動的に推論することは非常に難しい モデル検査器によるシステム Path sensitive な解析をするのでさまざまな同期機構に対応できる しかし open program には対応できない 静的 Lockset algorithm

Static Race Detection はどうあるべきか? 5 つの指標を掲げている 正確さ False positive (誤検知) の確率は十分に低いか? スケーラビリティ 大規模なプログラムも現実的な時間で解析できるか? 幅広い同期機構への対応 現実に用いられている同期機構に対応できるか? それ自身で閉じていないプログラム(ライブラリや デバイスドライバ等)への対応 (デバッグのための)反例生成の枠組み

Chord 中核は k-object sensitivity[Whaley, Lam 2004] による エリアス解析 BDD (Binary Decision Diagram) を用いて効率化 bddbddb[Lam, Whaley 2005] による実装 全体として 4 つのステージ Reachable-/Aliasing-/Escaping-/Unlocked-Pairs Computation いずれも実行箇所のペア(別スレッドで同時に実行される箇所を抽出したいことに注意)を扱う 各ステージで、race にならないものを枝狩りしていく Flow-insensitive な解析 ⇒ Unsound な手法 False positive/false negative が出る可能性がある

Chord: システム構成図

Open Program の扱い それ自体では完結しないプログラムは、補完してから検証の必要がある ライブラリ等は、自身がどのように呼び出されるかわからない (missing caller) テスト用の harness を生成してやる必要 またプログラムが依存するライブラリの挙動が不明な場合もある (missing callee) Java の native method など Chord では一部をモデル化し、それ以外は nop と等価として扱っている (このあたりも unsoundness の要因)

Test Harness Synthesis プログラムを解析するにあたって、エントリ ポイント(main)を自動生成 チェックしたいインターフェイス(I とする)に含まれるメソッドの引数をローカル変数として準備 参照型の変数に、非決定的に同じ型の値を代入 I のそれぞれのメソッドを、上で準備した値を用いて非決定的に呼び出し、結果を型の合う変数に代入 詳細は後ほど例を出します

Synchronization Idioms Java にはいくつかの同期手法がある synchronized(expr) { … } 自然に扱うことができる fork/join synchronization Flow sensitive な(プログラムの場所を考慮する)解析が必要 Chord は flow insensitive なので、ユーザが annotation をつけてやる必要がある オブジェクトのモニタ (Object#wait/notify) あまり重要ではない、と著者らは書いている

Stage 1: Reachable-Pairs Computation

Original-Pairs Computation まず最初に、プログラムの中で同じ変数を 使う可能性のある場所をすべて列挙する インスタンス変数 f、static 変数 g、配列 a への read/write アクセスを行う場所の組 Soot framework[R. Vallée-Rai et al. 1999] により求める インスタンス変数は、同一インスタンスの中のみを考慮すればよい しかしこれはものすごく大雑把な解析 ⇒ 後段の解析により refine していく

Original-Pairs Computation

Original-Pairs Computation: 例 public class A { int f; public A() { this.f = 0; } private int rd() { return this.f; } private int wr(int x) { this.f = x; return x; } public int get() { return this.rd(); } public synchronized int inc() { int t = this.rd() + (new A()).wr(1); return this.wr(t); } write read OriginalPairs = {(fr, fw), (fw, fw), (fr, f’w), (f’w, f’w), (fw, f’w)}

Reachable-Pairs Computation プログラムのエントリポイントから到達可能でなければ race は起こらない Race を起こす組は、main からどこかスレッドを 立ち上げる箇所を経由して到達可能なはず 到達可能性により Original-Pairs を枝狩り コールグラフ(呼び出し-呼び出されの関係をグラフにしたもの)の解析による

Call Graph 遷移関係の定義 →n、⇒n も帰納的に定義できる   は call site と context から、そこで呼ばれる メソッドと context の組を与える関数 Ifork は、スレッドを立ち上げる(thread-spawning) call site の集合 → と ⇒ の違いは、スレッドの起動が起こりうるかどうか →n、⇒n も帰納的に定義できる

Computation of Reachable Pairs Call Graph の関係(の反射推移閉包)を 用いて、次のように計算される   は main から到達可能な thread-spawning call site とコンテクストの集合    は call site (またはメモリアクセス)からそれが含まれるメソッドを返す関数 ReachablePairs が求める集合

Reachable-Pairs Computation: 例 public class A { public int get() { return this.rd(); } public synchronized int inc() { int t = this.rd() + (new A()).wr(1); return this.wr(t); } static public void main() { A a; if(*) a = new A(); if(*) a.get(); if(*) a.inc(); Test Harness コンストラクタの race は検出しないので消える ReachablePairs = {(fr, fw), (fw, fw), (fr, f’w), (f’w, f’w), (fw, f’w)}

Reachable-Pairs Computation: 例 public class A { public int get() { return this.rd(); } public synchronized int inc() { int t = this.rd() + (new A()).wr(1); return this.wr(t); } static public void main() { A a; if(*) a = new A(); if(*) a.get(); if(*) a.inc(); ReachablePairs = {(fr, fw), (fw, fw), (fr, f’w), (f’w, f’w), (fw, f’w)} ReachablePairs = {(fr, fw), (fw, fw), (fr, f’w), (f’w, f’w), (fw, f’w)} ReachablePairs = {(fr, fw), (fw, fw), (fr, f’w), (f’w, f’w), (fw, f’w)}

Stage 2: Aliasing-Pairs Computation

Aliasing-Pairs Computation 同じ変数実体に同時にアクセスしていない限り race は起こらない あるオブジェクトの異なるインスタンスにある同一名の変数 エリアスしていない配列へのアクセス エリアスしていてもインデックスが異なれば race にはならないが、ここでは保守的にインデックスは省いて考えている Reachable-Pairs として計算されたものから エリアス解析により枝狩り k-object sensitive alias analysis[Milanova et al. 2002] の手法をここでは用いる Flow insensitive, context/object/field sensitive analysis Inclusion-base analysis

エリアス解析 (Alias Analysis) オブジェクトへの参照が同じ場所を指して いるかどうかを静的に解析する手法 参照 = ポインタ(C, C++)、参照(C++, Java, C# ...) たとえば、次のコードは安全か? void swap(int* x, int* y) { *x ^= *y ^= *x ^= *y; } x == y だったら *x も *y も 0 になってしまう! そうならないことを保証するために、エリアス解析が有効

Stage 3: Escaping-Pairs Computation

Escaping-Pairs Computation 複数のスレッドに共有されていないデータは race を引き起こさない Aliasing-Pairs をさらに枝狩りできる データ共有のためには 2 つの場合がある メソッド呼び出し(thread-spawning)における引数 explicit な呼び出し(java.lang.Runnable#start) implicit な呼び出し(main から) オブジェクトのフィールドとしての共有

Stage 4: Unlocked-Pairs Computation

Unlocked-Pairs Computation (共通の)ロックをとっている組は race を引き起こさない Call graph と alias analysis から導出できる しかし計算量等の観点から、いくつか unsound な仮定が必要になる 次で説明

Unlocked-Pairs Computation UnlockedPairs’’ ⊆ UnlockedPairs’ になっている (証明済) つまり、false positive が出る可能性がある May-alias の解析しかしていない 「正しく」やるためには、must-alias (True と判断された場合は必ず alias)の解析が必要 ⇒ Chord が race-free と結論づけた場合でも、ひょっとすると別のオブジェクトに対して同期しているかもしれない False negative が出る可能性がある しかし実験中にそのような不都合は起きなかった、とのこと

後処理 最後まで残った変数アクセスの組を race の可能性があるものとして報告 そこに至るまでのパスを反例として出力 どの変数、またはオブジェクトが race を起こして いるのかを表示する しかし最終的に本当のバグによるものかを 判断するには人手が必要

Unlocked-Pairs Computation: 例 public class A { int f; public A() { this.f = 0; } private int rd() { return this.f; } private int wr(int x) { this.f = x; return x; } public int get() { return this.rd(); } public synchronized int inc() { int t = this.rd() + (new A()).wr(1); return this.wr(t); } inc() は synchronized メソッドなので、同時に到達することはない Escaping-Pairs = {(fr, fw), (fw, fw)}

Chord の評価実験 実際に広く使われているプログラムを検証

実験結果 (1) 速度 アノテーションはほとんど 必要なかった 646KLoC を 30 分弱で検査完了 大規模プロジェクトでも使用に耐える 手動でつけてもそれほど 苦にはならない

実験結果 (2) 発見された race 実際開発者に報告して修正がされたケースも False alarm が出ている箇所はさほど多くない Apache commons-pool における 17 箇所のバグの指摘に対し、実際に 5 箇所に修正パッチが出た

まとめ 静的解析により race を見つけ出すための 画期的な手法を提案した bddbddb を用いてシステムを実装した 広く使われている(マルチスレッド)プログラムを 用いてベンチマークを行った かなり巨大なプログラムでも現実的時間内で解析可能であることが確かめられた False positive の数が少ないことが確かめられた 実際にバグの解決に役立った事例もある