Java バイトコードの世界を旅しませんか?この記事では、始めるために知っておくべきことをすべて説明します。
1995 年に遡ると、Java プログラミングの作成者である Sun Microsystems は言語、大胆な主張をしました。 Java を使えば「一度書けばどこでも実行できる」と彼らは言いました。これは、コンパイルされたバイナリが任意のシステム アーキテクチャ上で実行できることを意味します。これは C では実行できず、今日に至るまで Java 作成の中核テナントであり続けています。
このクロスプラットフォーム機能を実現するために、Java は次の機能を採用しています。コンパイル時のユニークなアプローチ。 Java は、ソース コードからマシン コード (各システム アーキテクチャに固有のコード) に直接移行するのではなく、プログラムをバイトコードとして知られる中間形式にコンパイルします。バイトコードは、特定のマシン言語に結び付けられず、特定のハードウェア アーキテクチャにも依存しない一連の命令です。この抽象化が Java の移植性の鍵です。
Java バイトコード命令を解釈して実行するプログラムは、Java 仮想マシン (JVM) と呼ばれます。 JVM は、各バイトコード命令を、それが実行されている特定のシステム アーキテクチャにネイティブなマシン コードに変換します。このプロセスは「ジャストインタイム」(JIT) コンパイルと呼ばれることが多く、Java バイトコードを任意のプラットフォーム上で可能な限り効率的に実行できます。
バイトコードは無効ですただし、JVM にとって役立つだけではありません。 Java クラスのバイトコードは、リバース エンジニアリング、パフォーマンスの最適化、セキュリティ調査、その他の静的分析機能に役立つため、JDK には、それを検査するのに役立つユーティリティが付属しています。
バイトコードの場合、それぞれ `boolean` プリミティブ型をボックス化解除およびボックス化する、`java.lang.Boolean`、`booleanValue`、および `valueOf(boolean)` の 2 つのメソッドを検討してください。 JDK に同梱されている javap` コマンドを使用すると、それぞれのバイトコードを確認できます。これを行うには、次のように、「-c」コマンドとクラスの完全修飾名を指定して「javap」を実行します。
public boolean booleanValue() { return value; } public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
結果として、` 内のすべてのパブリック メソッドのバイトコードが得られます。 java.lang.Boolean`。ここでは、`booleanValue` と `valueOf(boolean)` のバイトコードだけをコピーしました。
javap -c java.lang.Boolean
バイトコードの分析
public boolean booleanValue(); code: 0: aload_0 1: getfield #7 // Field value:Z 4: ireturn public static java.lang.Boolean valueOf(boolean); Code: 0: iload_0 1: ifeq 10 4: getstatic #27 // Field TRUE:Ljava/lang/Boolean; 7: goto 13 10: getstatic #31 // Field FALSE:Ljava/lang/Boolean; 13: areturn一見すると、これは学習すべきまったく新しい言語です。ただし、各命令が何を行うのか、そして Java がスタックで動作することを学ぶと、すぐに簡単になります。
`booleanValue` の 3 つのバイトコード命令を例に挙げます。
`aload_n` は、ローカル変数への参照をスタックに配置することを意味します。クラスインスタンスでは、`aload_0` は `this` を参照します。
`getfield` は、`this` (スタックの下位項目) からメンバー変数を読み取り、それを配置することを意味します。スタック上の値
`#7` は定数プール内の参照のインデックスを参照します
`// フィールド値:Z` は伝えます`#7` が何を指すのか、`boolean` 型の `value` という名前のフィールド (Z)
`ireturn` はプリミティブ値をポップすることを意味しますスタックから取り出して返します
簡単に言えば、これら 3 つの命令はインスタンスの `value` フィールドを検索して返します。
2 番目の例として、次のメソッド `valueOf(boolean)` を見てください。
`iload_n` は、プリミティブなローカル変数をスタックに配置することを意味します。 `iload_0` は最初のメソッド パラメータを指します (最初のメソッド パラメータはプリミティブであるため)
`ifeq n` はスタックから値をポップし、それが true かどうかを確認することを意味します。存在する場合は次の行に進み、そうでない場合は行 `n`
`getstatic #n` はスタックに静的メンバーを読み取ることを意味します
`#27` は、定数プール内の静的メンバーのインデックスを参照します
`// フィールド TRUE:Ljava/lang/Boolean` は、`#27` が何を参照しているかを示します、タイプ `Boolean
`goto n` の `TRUE` という名前の静的メンバーは、バイトコード
実際の例として、私は最近、サードパーティのパッケージもつれ分析ツールを Ci システムに統合しようとしていました。残念ながら、このベンダーはクローズドソースであり、独自の UI を介してライブラリにアクセスする方法に関するドキュメントしかありませんでした。バイトコードを分析することで、基盤となる分析エンジンの予想される入力と出力をリバース エンジニアリングすることができました。
以上が楽しみながら利益を得るために Java バイトコードを読み取る方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。