JVMスタックフレーム動作とオペランドスタックローカル変数テーブル

事前知識

プライマー

デザインモードレジスタ

限り、我々は既知またはx86命令セットをアームとして、データレジスタに基づいて、その動作です。例えば、二つの加算を実行するためには、これら二つの数字は、その後、理解しやすく、認知のための私達のプログラミング言語と一致する、加算演算を実行するために2つのレジスタに供給されて動作する必要があります。

スタックベースのデザインパターン

クロックがスタックに格納されたスタックベースの設計データであり、スタックは、スタックからのデータを使用する必要があり、対応する動作を実行するであろう。

図に示すように、例えば、プロセスは、JVMの変化= B + Cバイトコードオペランドスタック及びローカル変数テーブルを実行しました。

3つのローカル変数a、bおよびc C、ローカル変数テーブルA、Bに格納され、それぞれ、第一のスタック
図1

番号2のスタックを保存するためにスタックの最上部には、加算演算、スタックのトップに結果に割り当てられたスタック番号の後にスタックの最上部を行います
図2

簡単な例

私たちはスタックする方法を学びました前のセクションとローカル変数テーブルに追加操作が完了している、我々は、このセクションのローカル変数の深さの研究が一覧表示されます。

ローカル変数テーブルを表示するには?

私たちは、道の逆コンパイル、クラスファイルのローカル変数テーブルで見ることができますが、ここでそのデザインは、より友好的、より人間的であるため、より多くの、IDEAのjclasslibプラグ(そこダイレクトサーチ)バイトコードビューを使用することをお勧めします。

ローカル変数テーブルの方法として

私たちは、これが達成されるか、インスタンスメソッドでは、私たちが直接が参照する必要がなく、メンバ変数や関数のインスタンスにアクセスできることをご存知ですか?
直接ハンズオンこのような問題、それは自然に明確な結果デコンパイル、テストクラスを作成します。
単純なクラスに、まず、

public class T {

    private int a = 0;

    public void add(int b,int c){
        a = b + c;
    }
}

第二に、クラスが選択され、その後の観点jclasslibとshowbytecodeを選択します
図3

結果は以下の通りであります:
図4

図を観察するために、我々の注目のaddメソッドを選択する方法は、一部を強調しました
図5

、コンパイルされたコードでJVMは、(この例で明らかに保存された引用)この参照内のローカル変数テーブルに追加こっそり、これはメンバ変数のインスタンスは、メソッドにアクセスすることができ、なぜ私たちの理由で、元は次のことを証明します
6

図の簡単な説明は、セクションコードで以下:
0)aload_0は、この基準スタックを参照する(aload_0今後のローカル変数テーブルのインデックス0をオペランドスタック上に押し付けている)
1)。iload_1におけるパラメータBスタック(ローカル変数インデックスは、オペランドスタックを押す1の整数である)
2)iload_2パラメータスタックC

この時点で、スタックの内容は、(スタックの最上部0)である
0.c
1.B
2.この

3)IADD二つの数字が追加されるスタック、スタックの一番上に結果を保存するが、このときのスタックの内容は
0.b + C
1.本

。4)。PutField第二の値に対応するメンバー変数を割り当てるスタックの2つの値スタック、最初の値(B + C)(これは)(はい、はいも二割り当てを実行する必要がCIポップ操作)
PutField(図に注意を強調表示)以下に記載する:
putfield
アドレス:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5 .putfield

結論

基于栈的指令集系统可以很方便的做到平台无关性(x86、arm),但也降低了性能,这也是为啥Java性能比C低原因。(操作寄存器快,还是操作栈快?哈哈)

おすすめ

転載: www.linuxidc.com/Linux/2019-08/160190.htm