OpenJDK+SystemTapを動かしてみよう
ここまでOpenJDKとSystemTapの概要について説明しました。今回は「Hello World」的なサンプルとして、「java -version」コマンド実行時に、Javaランチャー(javaコマンド)が明示的にロードするクラスを列挙してみます。
■ Javaランチャーとは?
「Javaランチャー」とは、JavaVMインスタンスを作成して、指定されたクラスのmainメソッドを呼び出すだけのJNIアプリケーションです。
通常は引数に与えられたクラス名や、JARの「マニフェスト(Main-Class)」に書かれているクラスをFindClass()関数でロードし、GetStaticMethodID()関数でmainメソッドのメソッドIDを取得して、CallStaticVoidMethod()関数で呼び出します。通常のJNI関数からJavaの戻り値のないstaticメソッドを呼び出す手順と変わりありません。
■ 動作を確認する環境
今回は以下の環境で動作を確認しました。OpenJDKは2011年8月時点での最新版を使用しています。
- OS:Red Hat Enterprise Linux Server 6.1(x86_64)
- SystemTap:systemtap-1.4-6.el6.x86_64(※インストールメディア同梱)
- OpenJDK:java-1.6.0-openjdk-1.6.0.0-1.39.1.9.8.el6_1.x86_64(※RHSA-2011:0856-1のエラータを適用)
なお、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で取得できる項目
今回サンプルで使用した、hotspot.jni.FindClassプローブで使用できる4つの変数の一覧を以下に示します。
- name
固定値で「FindClass」が入っている - env
FindClass()の第1引数(env)の値。使用したJNIEnvへのポインタ - clazz
FindClass()の第2引数(name)の値。ロードする完全修飾クラス名 - probestr
プローブ呼び出し時の概要の文字列表現
次回は、OpenJDK+SystemTapの5つの使用例
今回は「OpenJDK+SystemTapの組み合わせで何ができるか?」を中心に説明しました。HotSpot VMに埋め込まれたプローブポイントを活用することで、ソースコードに手を加えずに、VMや(クラスライブラリを含む)JNI実装を深いレベルでデバッグ可能になります。
プローブポイントはVM内で定義された個所だけでなく、libc内の任意の関数や(SystemTap本来の機能である)カーネル内関数など、さまざまな所に仕掛けられます。
ぜひお手元のマシンで、Javaアプリケーションがネイティブレベルでどのように動作しているのか、確認してみてください。
次回は、以下のようなOpenJDK+SystemTapの使用例を5つ紹介します。
- GC動作状況の取得
- 特定メソッドのプロファイリング
- 特定メソッド実行時のスタックトレース取得
- エンドポイントとのコネクション(ソケット)確認
- 競合するモニタオブジェクトの把握
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Webアプリの問題点を「見える化」する7つ道具
現場から学ぶWebアプリ開発のトラブルハック(1) 現場でのトラブル発生時に原因がなかなか掴めず、あたふたした経験はありませんか? そんなときには、このハック! - あなたの知らないJDKの便利ツールたち
安藤幸央のランダウン(43) 最近のJDKに含まれている開発やデバッグに便利なツールを、プロファイリングや情報取得、監視、配備、スクリプティングの5種類に分けて紹介 - プロファイラでメモリリークとパフォーマンス問題を解決
Java開発の問題解決を助ける(2) フリーで利用できるプロファイラ「NetBeans Profile」を使ってメモリリークとパフォーマンスの問題を解決する方法を紹介する - Javaパフォーマンスチューニング
JVMレベルにとどまらず、OSのカーネル・パラメータやネットワーク・パラメータのレベルでのチューニングを6回の連載で紹介する - チューニングのためのJava VM講座
パフォーマンスチューニングに関わるエンジニアのためのJava VM講座。2回に渡ってHotSpot VMの基礎知識を解説します - デバッグのヒント教えます
Javaエンジニアの皆さんが必ずぶつかるデバッグについて、実例を挙げながらその具体的な対処法について解説していきます - 高負荷なのに片方のサーバにだけ余裕が……なぜ?
Linuxトラブルシューティング探偵団 第1回 Linuxベースのシステムで起こるトラブルに、百戦錬磨の達人が立ち向かう! 実例を元に障害対応のプロセスを紹介します