JVM_03ランタイムデータエリア1_Stack_OperandStack_Operand Stack

オペランドスタック(オペランドスタック)

スタック:配列またはリンクリストを使用して実装できます

  • ローカル変数テーブルに加えて、各独立スタックフレームには、後入れ先出しのオペランドスタックも含まれます。これは、式スタックの
    オペランドスタックになることもできます。メソッドの実行中に、に従ってスタックに転送されます。バイトコード命令データの書き込みまたはデータの抽出、つまりプッシュまたはポップ

    • 一部のバイトコード命令は値をオペランドスタックにプッシュし、残りのバイトコード命令はオペランドをスタックから取り出して使用し、結果をスタックにプッシュします。(バイトコード命令のバイプッシュ操作など)
    • 例:コピー、スワッピング、合計などの操作を実行します。
      ここに画像の説明を挿入します
2.4.1概要
  • オペランドスタックは、主に計算プロセスの中間結果を保存するために使用されると同時に、計算​​プロセスの変数の一時ストレージスペースとして使用されます。

  • オペランドスタックは、JVM実行エンジンの作業領域です。メソッドの実行が開始されると、新しいスタックフレームも作成されます。このメソッドのオペランドスタックは空です。

  • 各オペランドスタックには、値を格納するための明確なスタック深度があります。必要な最大深度はコンパイラによって定義され、max_stackの値としてメソッドのコード属性に格納されます。

  • スタック内の任意の要素は、任意のJavaデータ型にすることができます

    • 32ビットタイプはスタックユニットの深さを占めます
    • 64ビットタイプは2つのスタック深度ユニットを占有します
  • オペランドスタックは、データアクセス用のインデックスへのアクセスには使用されませんが、データアクセスを完了するための標準ブリックのプッシュおよびポップ操作によってのみ使用されます。

  • 呼び出されたメソッドに戻り値がある場合、その戻り値は現在のスタックフレームのオペランドスタックにプッシュされ、PCレジスタで実行される次のバイトコード命令が更新されます。

  • オペランドスタック内の要素のデータ型は、コンパイル中にコンパイラによって検証されるバイトコード命令のシーケンスと厳密に一致する必要があり、クラスのロードプロセス中のクラス検証フェーズのデータ​​フロー分析フェーズで再度検証される必要があります。 。

  • さらに、Java仮想マシンの解釈エンジンはスタックベースの実行エンジンであり、スタックはオペランドスタックを参照します。

  • 上の図と次の図を組み合わせて、メソッド(スタックフレーム)の実行プロセスを確認します。

①15をスタックに格納します。②15、15をローカル変数テーブルに格納します。

ここに画像の説明を挿入します
③8を押します;④ローカル変数テーブルに8、8を格納します。

ここに画像の説明を挿入します

**⑤ローカル変数テーブルからインデックス1と2のデータを取得し、オペランドスタックに配置します。⑥加算演算を追加すると、8と15がスタックからポップアウトします
**
ここに画像の説明を挿入します

**✓iadd操作23の結果はスタックにプッシュされます;⑧23はローカル変数テーブルのインデックスが3である位置に格納されます
**

ここに画像の説明を挿入します

トップオブスタックキャッシング(ToS)
  • スタックアーキテクチャに基づく仮想マシンで使用されるゼロアドレス命令はよりコンパクトですが、操作を完了するにはより多くのスタックおよびポップ命令を使用する必要があります。つまり、より多くの命令ディスパッチ(命令ディスパッチ)時間が必要になります。メモリの読み取り/書き込み時間
  • オペランドはメモリに格納されているため、メモリの読み取り/書き込み操作を頻繁に行うと、必然的に実行速度に影響します。この問題を解決するために、HotSpot JVMの設計者は、スタックのすべての最上位要素を部屋のCPUのレジスタにキャッシュし、それによってメモリへの読み取り/書き込みの数を減らすスタックトップキャッシュテクノロジを提案しました。流行の実行効率を改善します。

おすすめ

転載: blog.csdn.net/qq_43141726/article/details/114581355