酔っぱらいシリーズ:ある工場の面接官に殴られて飲んだ後に仕分けされたJVM乾物

上の青いフォントをクリックして、「スター公式アカウント」を選択してください

高品質の記事、すぐに配達

99セットのJavaエンタープライズレベルの実際の戦闘プロジェクト

4000Gアーキテクト情報

リード:公式アカウントでは、飲んだ後に一連の技術記事を発表します。これらはすべて乾物であり、酔わないように願っています。

非常に基本的で、非常に基本的で、非常に基本的で、重要なことを3回伝えているので、なぜそのような記事を書きたいのですか。うーん、面接でよく聞かれるからじゃないですよね、ははははは????だから、落ち着いてこの記事を残酷に書いたので、普通の面接官にも対応できるようになりました。激しい戦いです。銃を挽いて準備をしましょう。

最初にこの写真を見てみましょう。何度も見たことがあると思いますが、今回は酔ったり戻ったりしないようにしましょう。

(赤いボックスはスレッドによって共有されるデータ領域であり、青いボックスはスレッドによって分離されたデータ領域です)

Javaプログラムの実行中に、Java仮想マシンは管理するメモリをいくつかの異なるデータ領域に分割します。これらの各領域には、作成と破棄の時間だけでなく、独自の目的があります。一部の領域は仮想マシンプロセスの開始時に存在し、一部の領域はユーザースレッドの開始と終了に応じて作成および破棄されます。

上の図を見ると、ランタイムデータを次の部分に明確に区別できます。

1. ????乾杯しましょう!敬意の最初のカップ、プログラムカウンター

プログラムカウンタは小さなメモリスペースであり、現在のスレッドによって実行されたバイトコードの行番号のインジケータとして見ることができます。バイトコードインタープリターが機能すると、このカウンターの値を変更して、実行する次のバイトコード命令を選択します。分岐、ループ、ジャンプ、例外処理、スレッド回復などの基本機能はすべて、このカウンターに依存して完了する必要があります。これはスレッドプライベートであり、各スレッドには独立したプログラムカウンターが必要です。

スレッドがJavaメソッドを実行している場合、カウンターは実行されている仮想マシンのバイトコード命令のアドレスを記録します。

実行がネイティブメソッドの場合、カウンター値は空です(未定義)。

このメモリ領域は、Java仮想マシン仕様でOutOfMemoryError例外を指定しない唯一の領域です。

2つ、????これを飲んだ後、あと3つグラスがあります![Java仮想マシンスタック]

スレッドはプライベートであり、そのライフサイクルはスレッドのライフサイクルと同じです。

仮想マシンスタックは、Javaメソッド実行のメモリモデルを記述します。各メソッドが実行されると、ローカル変数テーブル、オペランドスタック、動的リンク、メソッド出口などの情報を格納するためのスタックフレームが作成されます。呼び出しから実行の完了までの各メソッドのプロセスは、仮想マシンスタック内のスタックフレームをプッシュしてスタックからポップアウトするプロセスに対応します。

Java仮想マシンの仕様では、この領域に2つの異常な条件が指定されています。スレッドによって要求されたスタックの深さが仮想マシンによって許可された深さよりも大きい場合、StackOverflowError例外がスローされます。

仮想マシンスタックを動的に拡張でき、拡張中に十分なメモリを適用できない場合、OutOfMemoryError例外がスローされます。

3.3番目のカップ[ローカルメソッドスタック]

ネイティブメソッドスタックと仮想マシンスタックの機能は似ていますが、違いは次のとおりです。仮想マシンスタックは仮想マシンがJavaメソッド(つまりバイトコード)を実行するのに役立ちます。ローカルメソッドスタックは使用されるネイティブメソッドです。仮想マシンサービスによって、ローカルメソッドスタックもStackOverflowErrorおよびOutOfMemoryError例外をスローします。

4.このカップを飲んだ後、実際には最後のカップしかありません[Javaヒープ]

仮想マシンの起動時に作成される、すべてのスレッドによって共有されるメモリ領域。このメモリオブジェクトの唯一の目的はオブジェクトインスタンスを格納することであり、ほとんどすべてのオブジェクトインスタンスがここにメモリを割り当てます。

Javaヒープは、ガベージコレクターによって管理される主要な領域であるため、「GC」ヒープ(ガベージコレクションヒープ)、またはジョークである「ガベージヒープ」と呼ばれることもあります現在のガベージコレクターはすべて世代別コレクションアルゴリズムを使用しているため、Javaヒープは新世代と旧世代に細分されます(この部分については後で詳しく説明します)。どの領域が分割されていても、関係はありません。ストレージコンテンツは、どの領域に関係なく、メモリをより適切に再利用したり、メモリをより速く割り当てたりするために、すべてオブジェクトインスタンスです。

Java仮想マシン仕様によれば、Javaヒープは、論理的に連続している限り、物理的に不連続なメモリ空間に置くことができます。実装では、固定サイズまたはスケーラブルとして実装できます。現在の主流の仮想マシンは、スケーラビリティ(-XmxおよびXmsによって制御されるに従って実装ますインスタンスの割り当てを完了するのに十分なメモリがヒープになく、ヒープを拡張できなくなった場合、OutOfMemoryError例外がスローされます。

役に立たないと言って、タレントに直行してください!

 このコードは、ヒープメモリの使用サイズと動作原理を示しています(ヒープメモリ動作の概略図を表示するには、[実行]-> [構成の実行]に「-XX:+ PrintGCDetails」と入力します)

public class JVMTest {
  
      public static void main(String[] args) {
        
          long maxMemory = Runtime.getRuntime().maxMemory(); //Java虚拟机试图使用的最大内存
          long totalMemory = Runtime.getRuntime().totalMemory(); //Java虚拟机中的内存总量
  
          System.out.println("MAX_MEMORY = " + maxMemory + "(字节)" + (maxMemory / 1024 / 1024) + "MB");
          System.out.println("TOTOL_MEMORY = " + totalMemory + "(字节)" + (totalMemory / 1024 / 1024) + "MB");
      }
  
  }

実行後の結果を次の図に示します。

もちろん、ガベージコレクションは、パラメーターを設定することによってトリガーすることもできます(ガベージコレクションメカニズムの原理を確認するには、[実行]-> [構成の実行]で設定「-XX:+ PrintGCDetails」を入力してください)

public class JVMTest {
  
      public static void main(String[] args) {
        
          long maxMemory = Runtime.getRuntime().maxMemory(); //Java虚拟机试图使用的最大内存
          long totalMemory = Runtime.getRuntime().totalMemory(); //Java虚拟机中的内存总量
  
          System.out.println("MAX_MEMORY = " + maxMemory + "(字节)" + (maxMemory / 1024 / 1024) + "MB");
          System.out.println("TOTOL_MEMORY = " + totalMemory + "(字节)" + (totalMemory / 1024 / 1024) + "MB");
  
          String str = "hello world, JVM!";
          while (true) {
              str += str + new Random().nextInt(88888888) + new Random().nextInt(99999999);
          }
      }
  
  }

次の図に示すように実行します。

ファイブ、???最後のカップ、終わった後は仲良しです【方法エリア】

スレッドによって共有されるメモリ領域は、クラス情報、定数、静的変数、仮想マシンによってロードされたジャストインタイムコンパイラによってコンパイルされたコードなどのデータを格納するために使用されます。

メソッド領域も連続したメモリを必要とせず、固定サイズまたは拡張可能を選択できます。また、ガベージコレクションを実装しないことを選択することもできます。HotSpot仮想マシンで開発されたほとんどのプログラマーは、ガベージコレクションがメソッド領域にまで及ぶため、メソッド領域を「永続生成」と呼びますが、「永続生成」という名前のように、データがメソッド領域(永続生成)に入るという意味ではありません。 「また、永遠に存在しますが、比較的言えば、この地域でガベージコレクションが発生することはめったにありません。この領域でのメモリ回復の目標は、主に定数プールの回復とヒープタイプのアンロードです。一般的に、この領域での回復結果は不十分であり、メモリリークを引き起こす可能性がありますが、この領域の回復はまだ必要です。

メソッド領域がメモリ割り当て要件を満たすことができない場合、OutOfMemoryError例外がスローされます。

ランタイム定数

プールはメソッド領域の一部です。クラスファイル内のクラスバージョン、フィールド、メソッド、およびインターフェイスの説明情報に加えて、コンパイラによって生成されたさまざまなリテラルおよびシンボル参照を格納するために使用される定数プールもあります。コンテンツのこの部分はクラスがロードされた後に入力されますメソッドが移動するランタイム定数プールに格納されます。

クラスファイル定数プールと比較した実行時定数プールのもう1つの重要な機能は、動的であるということです。Java言語では、コンパイラーのみが定数を生成する必要はありません。実行時に新しい定数をプールに配置することもできます。この機能開発者が使用するのは、Stringクラスのintern()メソッドです

実行時の定数プールのメソッド領域の一部は、当然、メソッド領域によって制限されます。定数プールがメモリに適用できなくなると、OutOfMemoryError例外がスローされます。

この5杯のワインを作った後、上の写真は次のようになります

この時点で、5杯のワインが完成しました。おそらく多くのクラスメートがすでに飲んでいます。少し酔っ払うのにちょうどいいです。インタビュアーにしましょう!クラスメートがまだ少しめまいがするなら、それは問題ではありません、私たちは将来も飲み続けましょう、私たちはあなたの量を練習しなければなりません、そして私たちは将来私たちが遭遇するインタビュアーを恐れません。

ホットな推奨事項がありますか?

乾物:クライアントの要求がサーバーに到達する方法を理解するためのテキスト

SpringBoot + Redis分散ロック:注文取得のシミュレーション

Spring CloudとDubboのどちらを選択するのですか?

-9を殺すだけでなく、SpringBootを正常に停止するいくつかの方法を共有します

乾物共有99セットの実際の戦闘プロジェクトと資料を受け取るため公式アカウント舞台裏返信「99

充電は、プロセスプログラマーのフラッシュ充電の宝に焦点を当てたい

記事が役に立ったら、それを読んで転送してください。

ご支援ありがとうございます(* ^ __ ^ *)

おすすめ

転載: blog.csdn.net/qq_17231297/article/details/106233786