= SOBA: Java バイトコード解析ツールキット =
soba は Java のプログラム解析を実装するためのクラスライブラリです.
バイトコードの読み込み・変換を行うための[http://asm.ow2.org/ ASMライブラリ]をベースに,制御フロー解析や制御依存解析,データ依存解析,動的束縛の解決といった基本的な機能を提供しています.
ファイルを読み込み,そのメソッド呼び出し関係を列挙する処理の例が example ディレクトリに収録されています.
他の解析ツールキット,たとえば WALA や Soot との違いについては,[http://doi.org/10.11309/jssst.33.4_4 コンピュータソフトウェア誌に掲載された解説論文] をご覧ください.
== SOBA を実行してバイトコードの中身を閲覧してみる ==
SOBA には解析情報をテキストで出力するユーティリティプログラム {{{soba.util.debug.DumpClass}}} クラスが含まれています.
バイトコードとは何か詳しく知らないという方は,まずこのテキスト情報を閲覧してみると良いでしょう.
たとえばWindows 環境で実行する場合,以下のようにクラスパスに必要ライブラリを設定し,引数に soba-core-0.1.0.jar 自身を渡すことができます.
{{{
java -classpath soba-core-0.1.0.jar;asm-all-5.0.3.jar;trove-3.0.2.jar soba.util.debug.DumpClass soba-core-0.1.0.jar
}}}
出力される文字列は,引数に渡した JAR ファイルの各クラスに含まれるメソッドのシグネチャ,メソッド内部のバイトコード命令の一覧,命令間のデータ依存関係,制御依存関係,制御フロー情報です.
バイトコード命令は ASM によって処理された形式のもので,バイトコード命令そのものではないラベルや行番号も命令のリストに含まれた形式になっています.
出力されるデータ量が多すぎるという場合,小規模なプログラムを相手に試してみてください.
{{{DumpClass}}} の引数にはクラスファイル,ディレクトリ,JARファイル,ZIPファイルを複数指定することが可能で,ディレクトリの場合はそのディレクトリ以下に配置されたすべてのクラスファイルを,JAR や ZIP も内部に含まれるクラスファイルの情報を出力します.
== SOBA を使ってプログラム解析を実装する ==
SOBA を使うことでプログラム解析を簡単に実装することができます.
soba.example.dump.DumpMethodCall クラスは,メソッドの呼び出し関係を出力するプログラムです.
このプログラムは,引数に解析対象の jar ファイルやディレクトリを指定すると,解析対象の各メソッドが
どのメソッドを呼び出すかを出力します.
13行目を実行するだけで,対象プログラムの解析が行われ,その結果が JavaProgram オブジェクトに格納されます.
14行目で取得している ClassHierarchy オブジェクトは,型階層情報を保持していて,動的束縛を解決することができます.
16行目の for ループで対象プログラム中の各クラスの情報(ClassInfo)を訪問します.
さらに,17行目の for ループでクラス内の各メソッドの情報(MethodInfo)を訪問します.
18行目で,訪問したメソッドのシグネチャを文字列で出力します.
19行目の for ループでメソッド呼び出し命令(CallSite)を訪問し,20行目でその呼び出し先を解決します.
呼び出し先が解析対象に含まれていない場合は解決結果が空になるため,21行目の if 文でそれをチェックしています.
解決結果が空でない場合は呼び出し先のメソッドの情報を出力し,空の場合は呼び出し元の命令を出力します.
このようなプログラムを記述することでメソッドの呼び出し関係を解析することができます.
{{{ code java
12: public static void main(String[] args) {
13: JavaProgram program = new JavaProgram(ClasspathUtil.getClassList(args));
14: ClassHierarchy ch = program.getClassHierarchy();
15:
16: for (ClassInfo c: program.getClasses()) {
17: for (MethodInfo m: c.getMethods()) {
18: System.out.println(m.toLongString());
19: for (CallSite cs: m.getCallSites()) {
20: MethodInfo[] callees = ch.resolveCall(cs);
21: if (callees.length > 0) {
22: for (MethodInfo callee: callees) {
23: System.out.println(" [inside] " + callee.toLongString());
24: }
25: } else {
26: System.out.println(" [outside] " + cs.toString());
27: }
28: }
29: }
30: }
31: }
}}}
== その他のプログラム例 ==
[https://osdn.jp/projects/soba/scm/git/JavaAnalysisToolsDemo/tree/master/JavaAnalysisToolsDemo/src/demo/soba/ SOBAの利用例]として,以下のソースファイルを公開しています.
いずれのファイルも,コマンドライン引数として渡されたディレクトリ,JARファイル内部のクラスファイルを対象に解析を実行する main メソッドを備えています.
ただし,これらのプログラムは,ソフトウェア科学会の会誌「コンピュータソフトウェア」掲載記事で使用した性能計測などの結果をそのまま得られるよう,一部の出力文がコメントアウトされた状態になっていますので,SOBAの出力結果を見てみたいという場合はコメント化を解除してお使いください.
||ファイル名||機能||
||[https://osdn.jp/projects/soba/scm/git/JavaAnalysisToolsDemo/blobs/master/JavaAnalysisToolsDemo/src/demo/soba/CallGraphPerformance.java CallGraphPerformance.java]||クラスファイルからメソッド呼び出し関係を抽出し,出力する処理を実行するプログラム.||
||[https://osdn.jp/projects/soba/scm/git/JavaAnalysisToolsDemo/blobs/master/JavaAnalysisToolsDemo/src/demo/soba/ClassHierarchyPerformance.java ClassHierarchyPerformance.java]||クラスファイルから継承関係を抽出し,すべてのメソッド呼び出しごとに動的束縛の解決結果を取得するプログラム.||
||[https://osdn.jp/projects/soba/scm/git/JavaAnalysisToolsDemo/blobs/master/JavaAnalysisToolsDemo/src/demo/soba/ControlAndDataDependencePerformance.java ControlAndDataDependencePerformance.java]||クラスファイルの各メソッドに対し,メソッド内部の制御依存関係とデータ依存関係を計算し出力するプログラム.||
||[https://osdn.jp/projects/soba/scm/git/JavaAnalysisToolsDemo/blobs/master/JavaAnalysisToolsDemo/src/demo/soba/DumpAnalysisClass.java DumpAnalysisClass.java]||クラスの一覧を出力するプログラム.||
[[ReleaseList]]
[[RecentTickets(limit=5)]]