楽しみながら利益を得るために Java バイトコードを読み取る方法

PHP中文网
リリース: 2024-10-22 13:03:13
オリジナル
1008 人が閲覧しました

Java バイトコードの世界を旅しませんか?この記事では、始めるために知っておくべきことをすべて説明します。

楽しみながら利益を得るために 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` という名前の静的メンバーは、バイトコード

  • `areturn` はスタックから参照をポップして返すことを意味します

言い換えると、これらの命令は、true の場合、最初のメソッド パラメータを取得することを示しています。 、その後 `Boolean.TRUE` を返します。それ以外の場合は、`Boolean.FALSE` を返します。

バイトコード分析の活用

これはリバース エンジニアリング、パフォーマンスの最適化、セキュリティ研究に役立つ可能性があると前述しました。

リバース エンジニアリング

サードパーティ ライブラリまたはクローズド ソース コンポーネントを使用する場合、バイトコード分析は強力なツールになります。バイトコードを逆コンパイルすると、これらのライブラリの内部動作を垣間見ることができ、統合、トラブルシューティング、互換性の確保に役立ちます。

プロプライエタリまたはクローズドソースの Java コードに遭遇した状況では、バイトコードを読み取ることが唯一可能な可能性があります。その機能を理解する方法。バイトコード分析により、クローズドソース アプリケーションの動作をリバース エンジニアリングして理解することができ、相互運用性やカスタマイズが容易になります。

実際の例として、私は最近、サードパーティのパッケージもつれ分析ツールを Ci システムに統合しようとしていました。残念ながら、このベンダーはクローズドソースであり、独自の UI を介してライブラリにアクセスする方法に関するドキュメントしかありませんでした。バイトコードを分析することで、基盤となる分析エンジンの予想される入力と出力をリバース エンジニアリングすることができました。


以上が楽しみながら利益を得るために Java バイトコードを読み取る方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート