HN公開: FlowTracker – Javaプログラムでデータフローを追跡
(github.com/coekie)FlowTracker: Javaプログラムのデータフロー追跡
FlowTrackerはJavaエージェントで、プログラムがデータを読み取り、操作し、書き込む方法を追跡する。これにより、ファイルおよびネットワークI/Oを確認し、入力と出力を結び付けて、出力がどこから来たのかを示す。これによって、Javaプログラムの出力が何を意味するのかを理解できる。
デモ
Spring PetClinicはSpringフレームワークのデモアプリケーションである。FlowTrackerの機能を示すために、PetClinicがHTTPリクエストを処理し、テンプレートとデータベースからHTMLページを生成する過程を観察する。ブラウザでデモを実行することも、動画を視聴することもできる。
- HTTP処理: FlowTrackerは、どのコードがどの出力を生成したのかを示す。たとえば、"HTTP/1.1" やHTTPヘッダーをクリックすると、その部分が
org.apache.coyoteパッケージのクラスによって生成されたことが分かる。 - Thymeleafテンプレート: プログラムが読み取った入力(HTMLテンプレート)が出力とどのように結び付いているかを示す。HTMLタグ名をクリックすると、その部分が
layout.htmlファイルに由来することが分かる。 - データベース: HTMLページのテーブル内の情報がデータベースから来ていることを示す。たとえば、テーブル内の
Georgeをクリックすると、その値がデータベースに由来することが分かる。
このデモはインメモリデータベースを使用しているため、SQLスクリプトまで追跡できる。MySQLデータベースを使用する場合は、データベース接続まで追跡できる。
使い方
FlowTrackerは現在、概念実証段階にあり、すべてのプログラムでうまく動作するとは限らない。また、多くのオーバーヘッドを追加するため、プログラムの実行速度が遅くなる。FlowTrackerエージェントのjarファイルをダウンロードし、Javaコマンドラインに追加して使用する。
内部の動作方式
簡単な説明
FlowTrackerはクラスファイル(バイトコード)にコードを注入し、メモリ内のデータとその由来を追跡する。主にテキストおよびバイナリデータ(String、char、byte配列)を追跡する。
- JDKメソッド呼び出しをFlowTrackerのメソッド呼び出しに置き換える。
- JDKの主要な箇所にコードを注入して入力と出力を追跡する。
- メソッド内でローカル変数とスタック上の値を追跡するために、データフロー分析とより深い計測を行う。
- メソッド呼び出しの前後、およびメソッドの開始時と終了時にコードを追加して、メソッド引数と戻り値を追跡する。
データモデル: Tracker
FlowTrackerのデータモデルの中核となるクラスと概念:
- Tracker: 追跡対象オブジェクトの内容と由来に関する情報を保持する。
- content: データが通過した内容。例:
InputStreamまたはOutputStreamを通過したすべてのバイト。 - source: 他のトラッカーのソース範囲に対する内容の範囲を関連付ける。
- content: データが通過した内容。例:
- TrackerRepository: 関心のあるオブジェクトとそのトラッカーを関連付けるグローバルマップを保持する。
- TrackerPoint: 単一のプリミティブ値を表すトラッカー内の位置を指す。
基本的な計測
Trackerを最新の状態に保つため、特定のJDKメソッド呼び出し時にFlowTrackerの hook メソッド呼び出しを挿入する。たとえば、System.arraycopy 呼び出しを com.coekie.flowtracker.hook.SystemHook.arraycopy 呼び出しに置き換える。
プリミティブ値、データフロー分析
プリミティブ値を追跡することは、より大きな課題である。たとえば、byte 値を追跡するために、メソッド内でローカル変数にトラッカーを保存する。
メソッド呼び出し
プリミティブ値がメソッド呼び出しの引数や戻り値として別のメソッドへ流れることをモデル化する。Invocation を用いて、引数と戻り値の PointTracker を保存する。
コード自体を由来として使う
コード自体に由来する値(例: プリミティブ定数やString定数)を追跡する。各クラスに対するトラッカーを生成し、定数が参照される際にそのトラッカーを参照する。
Stringリテラル
Stringリテラルを新たにコピーし、Stringの内容を ClassOriginTracker と関連付ける。たとえば、String s = "abc"; は String s = StringHook.constantString("abc", 1234, 81); に書き換えられる。
追跡されていない値に対する代替手法
プログラム内のすべての値を追跡するわけではない。追跡されていない値が追跡すべき場所に到達した場合、それを定数と同様に扱う。
GN⁺のまとめ
- FlowTrackerはJavaプログラムのデータフローを追跡し、プログラムの出力を理解するのに役立つ。
- Spring PetClinicデモを通じて、HTTPリクエスト処理、テンプレート使用、データベース連携を視覚的に確認できる。
- 現在は概念実証段階であり、すべてのプログラムでうまく動作するとは限らず、性能オーバーヘッドも大きい。
- データフロー分析とメソッド呼び出し追跡を通じて、プリミティブ値とオブジェクトの由来を追跡する。
- 類似機能を持つツールとしては、Dynatrace、New Relicなどがある。
1件のコメント
Hacker News の意見
Clojure向けの FlowStorm というツールを紹介
Java/JVM エコシステムのツールが非常に優れていると称賛
HTML 要素から SQL 文まで追跡するデモに感銘を受けた
Smalltalk 環境を思い起こさせる
デモ動画が非常に有用であることを強調
HTML ソースマップに似た概念を試した経験を共有
Eve-lang のデモに似ていると言及
SQL インジェクションを動的に見つけるツールに似た論文を思い出した
インターネット上のデータを追跡するというビジョンを持っていた経験を共有
VSCode とプロジェクトでこのツールを試そうとしたことへの感謝