JVMランタイムデータ領域(JDK8に基づき、バイトコードと独自の理解を組み合わせたもの)

JVMと並行性とJavaは2つの高度なトピックです。今日は、JVM構成の一部について説明します。これは、日常の作業に最も密接に関連しているJVMランタイムデータ領域でもあります。
JVMの全体的な構造を見てみましょう。
JVM構成
私たちが作成するソースファイルはコンパイラを通過します(JavacコンパイラなどのJava仮想マシンもクロスプラットフォームであり、JRubyや他の言語などの他の言語は、独自の言語のコンパイラによってバイトに供給されます。コードのコンパイル)バイトコードを格納するClassファイルにコンパイルした後、後続の作業はJava仮想マシンに引き継がれます。クラス読み込みサブシステムは、クラスを記述するデータをClassファイルから実行時データ領域のメソッド領域(JDK1.8以降のメタスペース)に読み込み、データを検証、変換、分析、および初期化し、最終的に仮想マシンで直接形成できます。使用されるJavaのタイプ。Javaコードを実行する場合、実行エンジンには、インタープリター実行(インタープリターによる)とコンパイル実行(JITインスタントコンパイラによる)、またはその両方の2つのオプションがあり、いくつかの異なるレベルのコンパイラが含まれる場合もあります。実行エンジン(インタプリタとジャストインタイムコンパイラに加えて、プリコンパイラが存在する場合があります)。実行エンジンは、JVMの実行中にガベージコレクションのデーモンスレッドも開始します。
一般的なプロセスを紹介した後、このタイムランタイムデータ領域のトピックに戻ります。

仮想マシンスタック(図の例のランタイムデータ領域のスタック領域に対応):
仮想マシンスタックは、LIFO後入れ先出しスタック構造の実装です。Javaスレッドは、仮想マシンスタックメモリ構造に対応しています。仮想マシンスタックは、これは、Javaメソッド実行のメモリモデルです。各メソッドは、ローカル変数テーブル、オペランドスタック、動的接続、メソッド出口などを格納するためのスタックフレームを作成します。これは、スタックからスタックへの仮想マシンスタックのスタックフレームに対応します。仮想マシンスタックは、スレッドが破棄されるとメモリ領域を解放するため、ガベージコレクションの管理は必要ありません。ただし、メソッドの呼び出しの深さが深い場合(再帰呼び出しなど)、スタックの深さが不十分になり、StackOverflowErrorが発生する可能性があります。-Xssパラメータを使用してスタックサイズを調整できます。
スタックフレームの各部分について詳しく説明します
。1.1ローカル変数テーブル(ローカル変数テーブル)は、さまざまな基本型、オブジェクト参照、returnAddressなど、メソッドパラメータとメソッド内で定義されたローカル変数を格納するために使用される一連の変数値ストレージスペースです。 。
ここに画像の説明を挿入
次に示すように、jclasslibプラグインを介して、Classファイルの各メソッドに対応するローカル変数テーブルを表示できます。method1の場合、赤い丸から、長さ、数値、長さ、およびnumはカスタム変数名で、これは何ですか?実際、これは現在のインスタンスオブジェクトを指す変数です。仮想マシンがローカル変数テーブルに変数を配置するのに仮想マシンが役立ち、静的に変更されたクラスメソッドの場合、そのローカル変数テーブルにはこのローカル変数はなく、クラスメソッドでこれを使用して現在のインスタンスオブジェクトを参照することはできません。興味のある友人はjclasslibプラグインを使用して、静的メソッドのローカル変数テーブルを観察できます。
1.2オペランドスタック(オペランドスタック)は、操作スタックとも呼ばれ、LIFOスタックでもあります。JVM命令は、基本的にはスタックベースの命令セットアーキテクチャです(一般的な物理マシンのレジスタベースの命令セットアーキテクチャに匹敵します)。命令ストリーム内のほとんどの命令はゼロアドレス命令です。これらは、作業のためにオペランドスタックに依存しています。たとえば、次に示すように、単純なint型の加算を実行します
ここに画像の説明を挿入
。iconst_1命令はint型の定数1をオペランドスタックにプッシュし、istore_1命令はint型の値をローカル変数1に格納します。iconst_2とistore_2は類似しており、定数2が演算にプッシュされますスタックをカウントし、スタックの一番上にある定数2を取得して、ローカル変数2に格納します。Javaのメソッド呼び出し命令も同様です。たとえば、バイトコードの17行目のaload 4命令は、ローカル変数4(operandStackオブジェクト)をスタックの一番上にプッシュし、バイトコードの19行目のinvokevirtual命令は、オブジェクトのクラスに従って実行される仮想メソッドを呼び出しますJavaのポリモーフィックメカニズムのバイトコード実装の一部でもあるインスタンスメソッドを呼び出す。
1.3動的リンク(動的リンク)は、ランタイム定数プール内のスタックフレームのメソッドへのスタックフレーム内の参照であり、この参照は、メソッド呼び出し(動的リンク)中に動的リンクをサポートするために保持されます。オペランドスタックの例の画像のバイトコードの19行目に、invokevirtualの後に#4があることがわかります。この#4は、Classファイル構造の定数プール内のメソッドへのシンボリック参照です。変更されたクラスメソッド(invokestatic命令に対応)、変更されたプライベートprivateメソッド(invokespecial命令に対応)一般的なインスタンスメソッドなどの仮想メソッドでは、実行時に特定のバージョンのメソッドを決定する必要があります。この部分は動的リンクと呼ばれます。
1.4メソッド出口(returnaddress)は、メソッドを呼び出したプログラムカウンタの値を格納する場合があります。メソッドには通常の出口または異常な出口がありますが、メソッドの終了後に行うべきこと、およびメソッドの実行を開始する場所を決定するために、メソッド出口が必要です。返されたバイトコード命令。

2つ目は、ローカルメソッドスタックです。
ローカルメソッドスタックは、ネイティブローカルメソッドの呼び出しを管理するために使用され、スレッドに対してプライベートです。ネイティブメソッドは、CまたはC ++言語で実装されます。通常、プラットフォーム関連の実装であり、通常はより効率的です。エンジンは、natvieメソッドを実行するときにローカルメソッドライブラリをロードする必要があります。

3番目に、プログラムカウンター(ランタイムデータ領域のPCレジスタに対応):
プログラムカウンターはPCレジスタとも呼ばれ、現在のスレッドによって実行されるバイトコードの行番号インジケーターと見なすことができます。CPU内のレジスタは、プログラムカウンタとも呼ばれます。CPU内のプログラムカウンタは、命令アドレスを保存します。CPUのコントローラは、プログラムカウンタの値に従ってメモリから命令を読み取り、デコードして実行します。プロセス。JVMランタイムデータ領域のプログラムカウンターも同様の機能です。仮想マシンの概念モデルでは、バイトコードインタープリターは、このカウンターを変更して、次に実行するバイトコード命令、ブランチ、ループを選択することで機能します。ジャンプ、例外処理、スレッド回復などの基本機能は、完了するためにこのカウンターに依存する必要があります。
プログラムカウンターもスレッドプライベートです。Javaマルチスレッドが同じCPUコアを使用して同時実行性を実現する場合、スレッドの切り替え後に正しい実行位置を復元するには、現在のスレッドによって実行されたバイトを記録するために、各スレッドに独立したカウンターが必要です。コード命令の行番号オペランドスタックを説明するサンプル図のバイトコード命令の左側にある赤い数字は、バイトコード命令の行番号です。

第4に、Javaヒープ:
Javaヒープ(Javaヒープ)は、仮想マシンの起動時に作成されるすべてのJVMスレッドによって共有されるメモリ領域であり、すべてのオブジェクトと配列がランタイムデータ領域に割り当てられます。ヒープスペースは、自動ガベージコレクションシステムによって回復され、プログラマーがメモリを割り当ててリサイクルする必要はありません。ヒープスペースは固定サイズにすることも拡張することもできます。-Xmsと-Xmxを使用して初期ヒープメモリと最大ヒープメモリを設定できます。通常は同じに設定することをお勧めします。ヒープにインスタンスオブジェクトのメモリ割り当てを完了するためのメモリがなく、ヒープが拡張できなくなった場合、OutOfMemoryErrorがスローされます。

5番目に、メソッド領域:
メソッド領域(メソッド領域)は、仮想マシンの起動時に作成されるすべてのJVMスレッドによって共有されるメモリ領域でもあり、型情報、定数、静的変数、さらにはコンパイラ(JIT )コンパイルされたコードキャッシュおよびその他のデータ。JDK1.8以前は、HotSpotは永続的な世代を使用してメソッド領域を実装していましたが、この設計では永続的な世代のオーバーフローの問題が発生する傾向があります。JDK1.8以降、メタスペースを使用してメソッド領域を実装し始めました。メソッド領域が新しいメモリ割り当て要件を満たせない場合、CGLibバイトコードの拡張や多数のJSPなど、多数のクラスを動的に生成することが多いアプリケーションなど、OOM例外がスローされます。
どんな欠点でも、私を訂正してください、ありがとう。
やりがいを感じたら、褒めてください、ありがとう!

元の記事を14件公開 賞賛3件 929回の訪問

おすすめ

転載: blog.csdn.net/sjz88888/article/details/104864256