あなたは本当に JVM を理解していますか? JVM のメモリ領域とその機能は何ですか?

あなたは本当に JVM を理解していますか? JVM のメモリ領域とその機能は何ですか?

1.0 序文

前回は、.class ファイルが jvm にロードされる方法について説明しました。しかし、JVM ではメモリはどのように分割されるのでしょうか?このメモリはどのメモリにロードされますか? JVM のメモリ分割も、面接中に必ず尋ねられる質問です。

1.1 JVM メモリ領域の分割とは何ですか?

実際、この問題は非常に単純です。 JVM が私たちが書いたコードを実行するとき、複数のメモリ空間を使用する必要があります。異なるメモリ空間は異なるデータを保存するために使用され、システムを実行するために記述したコード フローと連携します。

最も簡単な例を見てみましょう。これで、JVM が後続の操作のためにクラスをメモリにロードすることがわかりました。そこでお聞きしたいのですが、これらのクラスはメモリにロードされた後、どこに配置されるのでしょうか?この質問について考えたことはありますか?

したがって、作成したクラスを保存するためのメモリ領域が JVM 内に存在する必要があります。

定義したメンバー変数、クラス変数、メソッド、ローカル変数などはすべて、JVM メモリ内のメモリの一部に対応し、記録および保存されます。

2.0 ストレージクラスメソッド領域

JDK 1.8 より前のバージョンでは、JVM の領域を表します。バージョン 1.8 以降、この領域の名前は「Matespace」に変更されました。これは「メタデータ スペース」と考えることができます。もちろん、主に自分たちで書いた各種クラスの関連情報が格納されます。

例えば。以下の2つのクラスがあります。 People クラスにはメンバー変数はありませんが、Student クラスには name というクラス変数があります。

  1. パブリッククラスStudent{
  2. プライベート静的文字列= "lisi" ;
  3. }
  4. パブリッククラス People {
  5. 公共 静的void main(){
  6. 学生 学生 = 新しい学生();
  7. }
  8. }

これら 2 つのクラスが JVM にロードされると、このメソッド領域に格納されます (注: 以前の章を読んでいれば、ここでのロードとは、ロード -> 検証 -> 準備 -> 解析 -> 初期化を意味し、クラスのすべてのクラス変数に値が割り当てられることを理解できます)。下記の通り

3.0 プログラムコード命令を実行するためのカウンタ

作成した .java ファイルがコンパイルされた後、jvm にロードされるクラス オブジェクトは .class ファイルであることがわかっています。

コンパイル後、コードはコンピュータが理解できるバイトコードにコンパイルされます。この .calss ファイルは、コードからコンパイルされたバイトコードです。

メモリにロードされると、バイトコード実行エンジンが動作を開始します。コンパイルしたコード命令を実行するには、以下に示すように

ここで疑問になるのは、バイトコード実行エンジンが現在実行しているコード行を記録するためにメモリ領域が必要かどうかです。この特別なメモリ領域は「プログラムカウンタ」です。

このプログラム カウンターは、現在実行されているバイトコード命令の場所を記録するために使用されます。

以下のように表示されます。

この時点で、混乱する人もいると思います。現在のコードシーケンスに従って実行するだけです。実行場所を記録する必要があるのはなぜですか?

記述するコードによって複数のスレッドが開始され、異なるコードが同時に実行される可能性があるためです。現在のスレッドがこのコードの実行をまだ完了しておらず、コンテキストが別のコードに切り替えられている可能性があります。

スレッドが再び前のコードにコンテキストを切り替える場合、現在のスレッドがどのバイトコードを実行したかを記録するための特別なレコードが必要になります。したがって、各スレッドには独自のプログラム カウンターがあります。

以下のように表示されます。

4.0 Java仮想マシンスタック

Java コードが実行されると、スレッドはメソッド内のコードを実行する必要があります。

スレッドがメソッドを実行するとき、そのメソッドにローカル変数がある場合は、ローカル変数のデータ情報を格納するための領域が必要になります。この領域は Java 仮想マシン スタックと呼ばれます。

各スレッドには独自の Java 仮想マシン スタックがあります。たとえば、メイン メソッドが実行されると、メイン メソッドで定義されたローカル変数を格納するメイン スレッドが存在します。

  1. 公共 静的void main(){
  2. People people = new People();
  3. 整数i = 9;
  4. }

たとえば、上記の main() メソッドには、実際には「people」というローカル変数があり、これは People のインスタンス オブジェクトを参照します。今のところこのオブジェクトは無視します。次に、「i」と呼ばれるローカル変数があります。

以下のように表示されます。


スタックのデータ構造、つまり後入れ先出しを誰もが知っておくべきだと思います。メソッドが実行されると、スタック フレームがポップされ、その中のローカル変数情報がメモリから削除されます。したがって、ローカル変数はスレッドセーフです。現在のスレッドだけがこの値を取得できるためです。

なぜ後入先出データ構造を使用するのですか?

メソッド a がメソッド b を同期的に呼び出すとします。この場合、メソッド a のスタック フレームが最初にスタックにプッシュされ、次にメソッド b のスタック フレームがスタックにプッシュされます。メソッド b が実行されると、メソッド b のスタック フレームがポップされ、メソッド a の実行が続行されます。したがって、後入れ先出しのスタック構造を使用するのが最適です。

現時点での JVM のメモリ モデル図は次のとおりです。


5.0 Java仮想マシンのヒープメモリ

この思い出はとても大切なものです。

インスタンス化するすべてのオブジェクトはこのメモリに保存されます。このインスタンス化されたオブジェクトには、いくつかのデータが含まれます。上記のコードを例として使用します。

  1. パブリッククラスStudent{
  2. プライベート文字列= "lisi" ;
  3. パブリック文字列getName(){
  4. 戻る 名前;
  5. }
  6. }
  7. パブリッククラス People {
  8. 公共 静的void main(){
  9. 学生 学生 = 新しい学生();
  10. 学生の名前を取得します。
  11. }
  12. }

このコードを引き続き使用すると、メイン スレッドが main() メソッドを実行すると、最初にヒープ メモリ内で Student オブジェクトがインスタンス化され、次にローカル変数に student が作成されます。 Student は、インスタンス化された Student オブジェクトのメモリ アドレスを格納します。次に、Student オブジェクトの getName() メソッドを実行します。

以下のように表示されます。

上の図からわかるように、スタック スペースは閉じられており、スレッド セーフですが、すべてのスレッドが実際にヒープ メモリ スペースを共有できるため、スレッドのセキュリティが主に発生するのはヒープ メモリです。

現時点での、jvm のメモリ分割の最終モデルは次のとおりです。

[[270808]]

6.0 その他のエリアメモリ

多くの Java プログラマーはこの分野にほとんど関わりがありません。

実際、NIO など、JDK の多くの低レベル コード API では、

ソース コードを見ると、多くの箇所のコードが Java で記述されておらず、ネイティブ メソッドを使用してローカル オペレーティング システム内のいくつかのメソッド (C 言語で記述されたメソッドである可能性があります) を呼び出していることがわかります。

例: public native int hashCode();

このネイティブ メソッドが呼び出されると、スレッドに対応するローカル メソッド スタックが生成されます。これは実際には Java 仮想マシン スタックに似ています。また、各種ネイティブ メソッドのローカル変数テーブルなどの情報も保存します。

JVM ではない別の領域があります。 NIO の allocateDirect API を使用すると、JVA ヒープ外にメモリ領域を割り当て、Java 仮想マシン スタック内の DirectByteBuffer を使用してオフヒープ メモリ領域を参照および操作できます。

7.0 要約

基本的にJVMのコアメモリ領域の機能がわかりやすく説明されています。ここまで答えられれば、スムーズに面接に合格できるはずです。

メソッド領域、プログラム カウンター、Java 仮想マシン スタック、Java ヒープ メモリといったメモリ領域の機能に注目する必要があります。

<<:  スキルギャップが拡大する中、クラウド時代の企業は主導権を握らなければならない。

>>:  SaaS の将来は人工知能とどのような関係があるのでしょうか?

推薦する

Dockerコンテナ技術のアーキテクチャとそのさまざまなモジュールを1つの記事で理解する

[[312463]]概要今日は、Docker の技術アーキテクチャと、それを構成するさまざまなモジュ...

クラウド コンピューティングの急速な発展は中小企業にとって何を意味するのでしょうか?

中小企業の経営者にとって、ビジネス界における新しいソフトウェアや開発のリスクとチャンスは恐ろしいもの...

AI、5G、クラウドコンピューティングは2021年にエッジコンピューティングにどのような影響を与えるでしょうか?

11 月 17 日のニュース、これまでのところ、エッジ コンピューティングは常に大きな可能性を秘めて...

Kubectl 経由でポッドを再起動する 6 つの方法

51CTOウェブサイトコンテンツ調査に参加するにはクリックしてくださいkubectl には rest...

Linode VPS レビュー/新しい SSD ディスク/E5-2680V2

一昨日、Linodeはアップグレードが完了したと発表しました。今回はハードウェアが大きく変わりました...

クラウド市場の「中核」プレーヤーであるUnigroup Cloudとその120億

清華紫光集団が3月末にパブリッククラウド分野への120億元の投資計画を発表して以来、清華紫光集団のク...

推奨: Kazila-$45/E3-1230V2/8G メモリ/1T ハードディスク/5IP/100M 無制限/IPMI

Kazila が朗報を発表しました。E3 シリーズ サーバーの特別価格、8G メモリ、SSD、100...

インタビュー |誰かが再び Kafka について尋ねてきたら、知らないとは言わないでください。

Kafka は優れた分散メッセージ ミドルウェアであり、多くのシステムでメッセージ通信に Kafka...

将来のクラウドコンピューティングの戦場では、ストレージが次の最前線となる

クラウド コンピューティングにおける価格競争は目新しいものではありません。 2014年、マイクロソフ...

Qiyiマーケティングモバイルフォンがあなたのリソースと能力を持続可能な富に変える方法

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますたくさんの...

完璧なプレミアムドメイン名を登録する方法

完璧なドメイン名は、あなたのサイトをユーザーに簡単に覚えさせることができます。当時、hao123 が...

Pinduoduo はなぜ成功しているのでしょうか?

数日前、 Pinduoduo は2019 年通期業績報告書を発表しました。報告書によると、Pindu...

推奨: securespeed-$3.5/1g メモリ/35g SSD/1T トラフィック/G ポート/ロサンゼルス/QuadraNET

securespeed.com は、月額 3.5 ドル、1G メモリ、35G SSD、1T トラフィ...

ウェブサイトのトラフィック統計分析についてもう一度お話しします

人生日記には、喜び、悲しみ、怒り、幸せ、そして成長体験を記録できます。では、ウェブサイトのトラフィッ...