| Javaプログラミング編 |
|
Sun Microsystems社より公開されているJVMの公式仕様『Java仮想マシン仕様(The Java Virtual Machine Specification)』(以下、JVM仕様)には、JVMで利用可能なバイトコードの仕様が説明されています。
JVM仕様では、バイトコードの命令列は、人間が読み取ることができるアルファベットの命令名(ニーモニック)と、その数値表現である1byteのオペコードで構成されています。クラスファイルはオペコードのみで構成されており、単なるバイナリデータです。試しにクラスファイルをテキストエディタで開いてみても、画像などのバイナリデータと同様に、文字にならないデータが表示されるだけです(クラスやフィールド、メソッドの名前は、バイトコード内にそのまま文字列として保存されているので、そこだけは何とか読み取ることができます)。
それでは、生成されたクラスファイルの中身を知ることはできないのでしょうか? 実は、あまり知られていませんが、そのような目的のためのツールが、JavaのSDKにデフォルトで用意されているのです。そのツールは「javap」というコマンドで、このコマンドを利用すればクラスファイルを人間が読み取れる形式に変換することができます。
javapコマンドは、引数にクラス名を渡して実行します。クラスファイルそのもの(つまり、「.class」拡張子が付いたファイルのパス)を渡すのではないことに注意してください。javapコマンドで指定できる主なオプションは、以下のとおりです。
javapコマンドの主なオプション| オプション | 説明 |
| -c | クラスファイルを逆アセンブルし、すべての命令列を表示する |
| -classpath <クラスパスのリスト> |
クラスパスを指定する |
| -extdirs <フォルダ> | 拡張フォルダの場所を変更する |
| -help | ヘルプを表示する |
| -l | 行番号とローカル変数テーブルを出力する |
| -public | publicなクラスとメンバ(注)を表示する |
| -protected | protected/publicなクラスとメンバを表示する |
| -package | private以外のクラスとメンバを表示する(デフォルト) |
| -private | すべてのクラスとメンバを表示する |
| -s | クラスファイル内で用いられる型シグネチャを出力する |
| -verbose | メソッド内のスタックサイズ、ローカル変数と引数の個数を出力する |
コマンドの使用法は、以下のとおりです。
> javap <オプション> <クラス名> |
それでは、簡単なサンプルクラスファイルを利用して試してみます。以下のソースコード「HelloWorld.java」をコンパイルして、生成されたクラスファイルを読むことにします。
| HelloWorld.java |
package net.mogra.wings.javatips; |
-cオプションを付けてjavapコマンドを実行すると、次のような結果が標準出力に表示されます(左端にある行番号は説明のために付加したもので、実際の出力には付いていません)。
1 > javac net\mogra\wings\javatips\HelloWorld.java |
この逆アセンブルされたクラスファイルについて、簡単に説明しておきます。
まず、3行目ではそのクラスファイルが作られた、元のソースコードのファイル名が表示されます。4行目は、そのクラスの宣言です。5〜9行目は、コンストラクタの命令列です。ソースコード「HelloWorld.java」にはコンストラクタはありませんでしたが、コンストラクタが省略された場合でも、バイトコードへコンパイルされるときにデフォルトのコンストラクタが挿入されるようになっています。コンストラクタの中では、インデックス0のローカル変数を読み込み(aload_0)、Objectクラスの初期化メソッドを呼び出し(invokespecial #9)、voidを返してメソッドを終了しています(return)。
11〜16行目が、ソースコードで宣言したmainメソッドの命令列になります。まず、Systemクラスのoutフィールドを読み込み(getstatic #21)、続いてStringオブジェクトの“Hello World!”を読み込んでいます(ldc #23)。その文字列を引数にしてprintlnメソッドを呼び出し(invokevirtual #29)、最後にvoidを返してメソッドを終了しています(return)。
このように、javapコンパイラを利用すれば、コンパイルされたクラスファイルの命令列を読み取ることができます。勉強やデバッグに利用してみてください。
| 「Java TIPS」 |
TechTargetジャパン
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承 (2012/5/22)
インポート、パッケージオブジェクト、抽象クラス/抽象メソッド、オーバーライド、final、シールドクラスなども - 基幹系システムでCloud SQLは使えるか試してみた (2012/5/17)
サンプルとしてMRPシステムを作成して動かし、「再帰呼び出し」などのパフォーマンスを測定して検証してみます - アジャイル管理ツール9選+Pivotal Tracker入門 (2012/5/14)
群雄割拠のアジャイルプロジェクト管理ツールを9つ紹介し、特に注目を集めているPivotal Trackerの基本的な使い方を解説します - サーバサイドJSやJavaでWebアプリが作れるXPages (2012/5/11)
Notes/Dominoの資産をサーバサイドJavaScriptやJavaで操作し、HTMLやJavaScript、CSSをUIにできる技術を紹介
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -
