JVMメモリ領域分割の深い理解

JVMメモリ領域分割の深い理解

[[436712]]

この記事はWeChatの公開アカウント「馬崇嘉」から転載したもので、著者は馬崇嘉です。この記事を転載する場合は、馬崇嘉公式アカウントまでご連絡ください。

1. Java ファイルはどのように実行されますか?

実行プロセス:

1. Javaファイルは.classバイトコードファイルにコンパイルされます。

2. バイトコードファイルはクラスローダーを通じてJVM仮想マシンにロードされます。

3. ロード後、JVM実行エンジンによって実行される

プログラム実行プロセス全体を通じて、JVM はプログラム実行中に必要なデータと関連情報を格納するためのスペースを使用します。この領域は一般にランタイム データ領域と呼ばれ、JVM メモリと呼ばれることもあります。

2. ランタイム データ領域を構成する要素は何ですか?

ランタイム データ領域には、主に次の 5 つのブロックが含まれます。メソッド領域とヒープはスレッド共有領域であり、スレッドの安全性の問題があります。 Java スタック、ローカル メソッド スタック、およびプログラム カウンターは排他的な領域であり、スレッド セーフティの問題はありません。 JVM のチューニングは主にヒープとスタックを中心に行われます。

1. 方法領域

各クラスの情報(クラス名、メソッド情報、フィールド情報を含む)、静的変数、定数、コンパイラによってコンパイルされたコードが格納されます。クラス ローダーが .class ファイルをランタイム データ領域にロードすると、最初にこの領域にスローされます。

クラス ファイルには、クラス フィールド、メソッド、インターフェイスなどの説明情報に加えて、コンパイル中に生成されたリテラルとシンボリック参照を格納するために使用される定数プールも含まれています。

メソッド領域で非常に重要な部分は、各クラスまたはインターフェースの定数プールのランタイム表現であるランタイム定数プールです。クラスとインターフェースが JVM にロードされた後、対応するランタイム定数プールが作成されます。もちろん、クラス ファイル定数プールの内容だけがランタイム定数プールに入るわけではありません。 String の intern メソッドなど、実行時に新しい定数を実行時定数プールに配置することもできます。

2.ヒープ

メソッド領域と同様にスレッド共有領域であり、主にオブジェクトインスタンスや配列などの保存されたデータが格納されます。

ヒープは Java ガベージ コレクターによって管理される主要な領域であり、JVM にはヒープが 1 つだけ存在します。

3. Javaスタック

Java スタックは、Java 仮想マシン スタックとも呼ばれます。 Java スタックは、Java メソッド実行のためのメモリ モデルです。

Java スタックはスタック フレームを 1 つずつ格納します。各スタック フレームは、呼び出されたメソッドに対応します。スタック フレームには、ローカル変数テーブル (ローカル変数)、オペランド スタック (オペランド スタック)、現在のメソッドが属するクラスのランタイム定数プールへの参照 (ランタイム定数プールの概念についてはメソッド エリアで説明します) (ランタイム定数プールへの参照)、メソッドの戻りアドレス (戻りアドレス)、およびその他の追加情報が含まれます。スレッドがメソッドを実行すると、対応するスタック フレームが作成され、作成されたスタック フレームがスタックにプッシュされます。メソッドが実行されると、スタック フレームがポップされます。したがって、スレッドによって現在実行されているメソッドに対応するスタック フレームは、Java スタックの最上部にある必要があることがわかります。この時点で、再帰メソッドを使用するとスタック メモリ オーバーフローが発生する可能性が高くなる理由と、スタック領域をプログラマーが管理する必要がない理由を誰もが理解しているはずです (もちろん、Java では、独自のガベージ コレクション メカニズムがあるため、プログラマーは基本的にメモリの割り当てと解放について心配する必要はありません)。このスペースの割り当てと解放はシステムによって自動的に実行されます。すべてのプログラミング言語において、スタック空間はプログラマーにとって不透明です。次の図は、Java スタック モデルを示しています。

ローカル変数テーブルは、その名前が示すように、説明がなくても誰もがその機能を理解できると思います。メソッド内のローカル変数 (メソッドおよび関数パラメータで宣言された非静的変数を含む) を格納するために使用されます。基本データ型の変数の場合はその値が直接格納され、参照型の変数の場合はオブジェクトへの参照が格納されます。ローカル変数テーブルのサイズはコンパイラによって決定できるため、プログラム実行中にローカル変数テーブルのサイズは変更されません。

オペランド スタック。データ構造のスタックについて学んだ人は、式の評価の問題に精通している必要があります。スタックの最も典型的な用途の 1 つは、式を評価することです。スレッドがメソッドを実行するプロセスについて考えてみましょう。これは実際にはステートメントを継続的に実行するプロセスであり、最終的には計算のプロセスです。したがって、プログラム内のすべての計算プロセスはオペランド スタックの助けを借りて完了すると言えます。

ランタイム定数プールへの参照。クラス内の定数はメソッドの実行中に使用される必要がある場合があるため、ランタイム定数への参照が必要です。

メソッドの戻りアドレス。メソッドが実行されると、メソッドは以前に呼び出された場所に戻るため、メソッドの戻りアドレスをスタック フレームに保存する必要があります。

各スレッドで実行されるメソッドは異なる可能性があるため、各スレッドには独自の Java スタックがあり、互いに干渉することはありません。

4. ネイティブメソッドスタック

Thread クラスのソース コードを開くと、start() メソッドが native キーワードで変更されており、メソッド本体がないことがわかります。ネイティブで変更されたこのメソッドはローカル メソッドです。

  1. プライベートネイティブvoid start0();

ネイティブ メソッド スタックと Java スタックの機能と原理は非常に似ています。唯一の違いは、Java スタックは Java メソッドの実行に使用され、ネイティブ メソッド スタックはネイティブ メソッドの実行に使用されることです。 JVM 仕様では、ローカルで開発された特定の実装方法やデータ構造に対して必須の要件を課していません。仮想マシンはそれを自由に実装できます。 HotSopt 仮想マシンでは、ネイティブ メソッド スタックと Java スタックが直接 1 つに結合されます。

5. プログラムカウンタ

プログラム カウンター レジスタ (PC レジスタとも呼ばれます)。アセンブリ言語を学んだ学生なら、プログラム カウンターの概念に馴染みがあるはずです。アセンブリ言語では、プログラム カウンターは、プログラムによって現在実行されている命令のアドレスを格納する CPU 内のレジスタを指します (次の命令が配置されている記憶装置のアドレスを格納するとも言えます)。 CPU が命令を実行する必要があるときは、プログラム カウンタから現在実行しようとしている命令が配置されているストレージ ユニットのアドレスを取得し、取得したアドレスに基づいて命令を取得する必要があります。プログラムカウンタは命令を取得した後、自動的に 1 を加算したり、転送ポインタに基づいて次の命令のアドレスを取得したりします。すべての命令が実行されるまでサイクルは継続されます。

JVM のプログラム カウンターは、アセンブリ言語のプログラム カウンターのような物理的な CPU レジスタではありませんが、JVM のプログラム カウンターの機能は、アセンブリ言語のプログラム カウンターの機能と論理的に同等であり、どの命令を実行するかを示すために使用されます。

JVM では、複数のスレッドが順番に切り替えることで CPU 実行時間を取得します。したがって、特定の瞬間には、CPU コアは 1 つのスレッド内の命令のみを実行します。したがって、スレッド切り替え後に各スレッドが切り替え前のプログラム実行位置を再開できるようにするには、各スレッドが独自の独立したプログラム カウンターを持ち、互いに干渉できないようにする必要があります。そうしないと、プログラムの正常な実行順序に影響します。したがって、プログラム カウンターは各スレッドに固有のものであると言えます。

JVM 仕様では、スレッドが非ネイティブ メソッドを実行する場合、プログラム カウンターに現在実行する必要がある命令のアドレスが格納されると規定されています。スレッドがネイティブ メソッドを実行する場合、プログラム カウンターの値は未定義になります。

プログラムカウンタに格納されるデータが占める空間のサイズはプログラムの実行に伴って変化しないため、メモリ領域の中で唯一OutOfMemoryErrorが発生しない領域であり、占有するメモリ空間も非常に小さいため基本的に無視できる程度です。

<<:  Kubernetes レプリケーション コントローラーの仕組み

>>:  生まれたばかりの子牛はトラを怖がらない!今年注目すべきクラウドコンピューティングのスタートアップ10社

推薦する

新しいウェブサイトを立ち上げた後、Baidu ランキングを素早く獲得する方法

多くのウェブマスターにとって、新しいウェブサイトを立ち上げた後にランキングを獲得することは緊急の課題...

クラウドネイティブデータベースが必要な理由

データベースは常にアプリケーション開発の非常に重要な部分です。 MySQL から Amazon の ...

ショッピングモールのウェブサイト運営でトラフィックを集める方法

立ち上げたばかりのショッピングモールのウェブサイトを運営するのは少し難しいです。ショッピングモールの...

地域生活サービス同質化分類情報サイトモバイル端末競争が激化

Admin5.comは10月12日、中国で最初の分類情報ウェブサイト群であるGanji.comと58...

JD.comがダブル11データを発表:注文量は通常の3倍

新浪科技新聞は11月11日午後、JD.comが一連の最近の販促データを発表した。11月11日午前0時...

racknerd: 複数のハイエンド ストレージ サーバー、$395、2*e5-2630Lv2/64g メモリ/300gSSD+160T HDD/100t トラフィック/5IP、アップグレード可能な構成

ユタ州ソルトレイクシティのデータセンターにある Racknerd の大型ハードドライブ サーバー (...

新しいウェブサイトは、Baidu の評価期間をどうやって乗り切るべきですか?

多くの友人は、ウェブサイトを構築するときにこのような問題に遭遇します。新しいウェブサイトがオープンし...

2018年の米国越境電子商取引市場の概要

本稿では、地域経済発展の現状と展望、消費者の洞察、ソーシャルメディアマーケティングのレイアウト、主要...

iniz-128m メモリ KVM 年間支払額 15.5 米ドル

128M メモリの KVM VPS で年間 15.5 ドルの支払いは、それでもかなりコスト効率が良い...

Alibaba Cloud Native 実践サミット: デジタル経済時代のクラウドネイティブ

著者: ユン・チャオ【51CTO.comオリジナル記事】導入昨年はクラウド ネイティブが爆発的に増加...

分散アーキテクチャシステムでグローバルに一意のシリアル番号を生成するためのアイデア

背景分散アーキテクチャでは、一意のシリアル番号を生成することは、特にデータベースがシャーディングを使...

マイクロソフトの第3四半期の収益はクラウドコンピューティングの好調に支えられ予想を上回る

財務報告によると、Azure クラウド事業はマイクロソフトの最大の成長原動力であり、同社の時価総額を...

Sina Weiboの無料リソースをすべて絞り出す - 実用的なWeiboツールの詳細説明(パート2)

パート3: ファン管理ファン管理はどのWeiboアカウントにとっても最も重要なタスクであると私は考え...

Didiの分散IDジェネレータ(Tinyid)、非常に便利な

分散IDジェネレータについて知らない人は、前回の「分散ID生成方法9選」を復習してください。 Tin...