ここまでOpenJDKとSystemTapの概要について説明しました。今回は「Hello World」的なサンプルとして、「java -version」コマンド実行時に、Javaランチャー(javaコマンド)が明示的にロードするクラスを列挙してみます。
「Javaランチャー」とは、JavaVMインスタンスを作成して、指定されたクラスのmainメソッドを呼び出すだけのJNIアプリケーションです。
通常は引数に与えられたクラス名や、JARの「マニフェスト(Main-Class)」に書かれているクラスをFindClass()関数でロードし、GetStaticMethodID()関数でmainメソッドのメソッドIDを取得して、CallStaticVoidMethod()関数で呼び出します。通常のJNI関数からJavaの戻り値のないstaticメソッドを呼び出す手順と変わりありません。
今回は以下の環境で動作を確認しました。OpenJDKは2011年8月時点での最新版を使用しています。
なお、OpenJDKとSystemTapを組み合わせて使用するには、最低でもOpenJDKの「debuginfo」パッケージが必要です。今回のOpenJDKに対応するdebuginfoパッケージは「java-1.6.0-openjdk-debuginfo-1.6.0.0-1.39.1.9.8.el6_1.x86_64」です。忘れずにインストールしてください。
コンソールにrootユーザーで、以下のコマンドを入力します。使用するコマンドは「stap」という、SystemTapのコマンドです。
上記はJNI関数FindClass()の入りにプローブを掛け(【1】)、変数clazzの内容を出力する(【2】)スクリプトをワンライナーで書いています(「-e」オプション)。情報の出力に使用している「println()」関数はJavaのSystem.out.println()メソッドと同様、指定された引数の内容を出力後、改行します。
最後に、このプローブ対象のコマンドとして「java -version」を渡しています(【3】:「-c」オプション)。
実行結果は以下のようになります。-versionオプションを付加しただけでも、さまざまなJavaクラスが明示的にロードされていることが分かります。
-versionオプションを指定した場合、そこで表示されるバージョン情報は「sun.misc.Version.print()で」標準エラー出力に出力されます。そのため、FindClass()のプローブで「sun/misc/Version」が検知されました(※JNIなので、パッケージのデリミタはドットではなく、スラッシュになります)。
今回サンプルで使用した、hotspot.jni.FindClassプローブで使用できる4つの変数の一覧を以下に示します。
今回は「OpenJDK+SystemTapの組み合わせで何ができるか?」を中心に説明しました。HotSpot VMに埋め込まれたプローブポイントを活用することで、ソースコードに手を加えずに、VMや(クラスライブラリを含む)JNI実装を深いレベルでデバッグ可能になります。
プローブポイントはVM内で定義された個所だけでなく、libc内の任意の関数や(SystemTap本来の機能である)カーネル内関数など、さまざまな所に仕掛けられます。
ぜひお手元のマシンで、Javaアプリケーションがネイティブレベルでどのように動作しているのか、確認してみてください。
次回は、以下のようなOpenJDK+SystemTapの使用例を5つ紹介します。
Copyright © ITmedia, Inc. All Rights Reserved.