最も単純なJVMメモリ構造図

JVMメモリ構造図


image.png

みなさん、こんにちは。数日間更新していません。今日の内容は少し多すぎます。JVMの内部構造図を詳しく紹介しましょう。以前と同じです。ケースが最初です。誰もが理解できるように、覚えておいてください。

/ **
 * @author:jiaolian
 * @date:2021-03-1021:28に作成
 * @description:helloworld testjvmメモリ領域
 * @によって変更:
 *公式アカウント:電話
 * /
パブリッククラスHelloWorldTest {

    public static void main(String [] args){
        //新しいHelloWorldTestオブジェクトを作成します;
        HelloWorldTest helloWorldTest = new HelloWorldTest();
        // sayHelloを呼び出す2つのスレッドを作成します
        for(int i = 0; i <2; i ++){
            new Thread(()-> helloWorldTest.sayHello( "world"))。start();
        }
    }

    / **
     *誰かに挨拶する
     * @param who
     * /
    public void sayHello(String who){
        System.out.println(Thread.currentThread()。getName()+ "hello!" + who);
    }
}

上記のコード:メインスレッドのforループに2つの新しいスレッドを作成して、sayHelloを呼び出し、最後の2つのスレッドはそれぞれhello to the world!このコードは理解しやすいので、出力結果は投稿されません。このコードを作成して実行しました。主に、このコードがJVMでどのように機能するかを確認します。

まず、HelloWorldTest.Javaファイルを作成します。このファイルは、javacのコンパイル後にバイトコードHelloWorldTest.class変換されます。なぜバイトコードに変換する必要があるのですか?Java仮想マシンがそれを認識できるからです!最後に、バイトコードはクラスロードサブシステムClassLoaderによってメモリにロードされます。メモリの各ブロックには独自の役割があり、最後に実行エンジンがバイトコードを実行します。以下では、メモリの各ブロックが果たす役割に焦点を当てます。

image.png


メソッドエリア


メソッド領域には、主に、クラスメタデータ、定数プール、メソッド情報、クラス変数などの静的情報が含まれています。上記のコードHelloWorldTest.classはクラスメタデータであり、sayHello、mainはメソッド情報などがメソッド領域に格納されます。メソッド領域には、次の2つの注意点もあります。

  1. メソッド領域が大きすぎて設定を超えると、OutOfMemoryError:PermGenスペースエラーが報告されます。gclibツールは、エラーをテストするためのクラスを動的に生成できます。
  2. JDK1.7より前は、メソッド領域は永続生成と呼ばれ、1.8以降はメタスペースと呼ばれていましたその理由は、管理プレッシャーを解放するために、JDK1.8が実行時定数プールを管理用のヒープに引き渡したためです。


ヒープ


ヒープは主にインスタンスオブジェクトを格納します。このように理解すると、キーワードnewが付いたオブジェクトが表示されている限り、データはヒープに格納されます。上記のコードはHelloWorldTestです。helloWorldTest= new HelloWorldTest(); helloWorldTestは、新しいHelloWorldTestオブジェクトインスタンスを指すHelloWorldTestオブジェクトへの参照です。helloWorldTest参照は、ローカル変数ローカル変数(で宣言されたオブジェクトタイプ)とも呼ばれるスタックに配置されます。メソッドまたは通常のタイプ)、次のヒープ、スタック、およびメソッド領域関係を示すために絵を描くだけです。JVMがHelloWorldTestを実行すると、helloWorldTest = new HelloWorldTest();この文では、JVMのメモリ構造は次のようになります。オブジェクトへの参照が消えた場合、オブジェクトはGCによってリサイクルされます。

image.png

ヒープメモリでは、メモリを若い世代古い世代の2つの領域に分割する必要があります以下に示すように。

  1. 新生代:ヒープメモリでは、新生代は3つの部分に分割されます。エデン(エデンは新しいオブジェクトに対応する新しい生命を作成します)、から、これらの3つのメモリ領域は新生代に属し、デフォルトの比率は8:1です。 :1、新しいオブジェクトはそれぞれ最初にedenに格納されます。edenエリアのメモリがいっぱいになると、モニターgcがトリガーされてエリアが再利用され、再利用されていないオブジェクトはfromまたはto、from、に配置されます。そのうちの1つが空で便利なメモリへオブジェクトはメモリ内で並べ替えられ、マークされます。オブジェクトが収集され、移動されたり移動されたりするたびに、再生されていないオブジェクトの年齢も1ずつ増加します。年齢(デフォルトは15歳)、それは古い年齢に入ります。
  2. 旧年齢:老齢がいっぱいになって、完全なGCの回復がトリガされるシステムが大きすぎると、フルGCが回復することはできませんプログラムはのように表示されます。。java.lang.OutOfMemoryErrorを:Javaのヒープ領域を我々-Xmx32mなどのJVMパラメータを設定できます。最大ヒープメモリを32Mに設定します。

ヒープを分割する理由は、JVMがガベージコレクション自動的に処理できるようにするためです。ヒープメモリは、GCによって収集される主要な領域です。

image.png



スタック


スタックメモリスペースは、ヒープスペースに比べて比較的小さく、スレッド専用です。スタックは主に、ファーストインとラストアウトのスタックフレームです。スタックフレームは、メソッドには、ローカル変数、メソッドパラメータ、およびメソッドが含まれます。エクスポート、定数ポインタへのアクセス、および例外情報テーブル。例外情報テーブルと定数ポインタ情報は、メソッド本体に表示されない場合がありますが、逆コンパイルされたものに反映できます。Jclasslibツールクラスを介してクラスファイルを作成し、例外情報テーブルを処理できます。プログラムがエラーを実行すると、実行する特定のコード行にジャンプし、JVMが例外テーブルを介してフィードバックされます。例と図を組み合わせて詳細に分析します。プログラムの実行中は、次の図に示すように、JVMのスタックが表示される場合があります。

image.png    

スレッドは複数のスタックフレームに対応する場合があります。次の図に示すように、スタックフレームは上から下に、最初から最後に押し込まれ、メソッドAでメソッドBを呼び出し、メソッドBでメソッドCを呼び出し、メソッドでメソッドを呼び出します。 C D、メインスレッドはスタックフレームのスタック状況に対応し、スタックシーケンスはD-> C- > B- > Aであり、最終プログラムは終了します。注:オペランドスタックは、ローカル変数計算の中間結果を格納することを意味します。たとえば、int x = 1はメソッドAで定義され、ローカル変数は、JVMでの後続の計算のためにオペランドスタックに配置されます。スタックにもスペースサイズがあります。スタックが大きすぎてスタックの深さを超えると、同様のエラーが報告されます。java.lang.OutOfMemoryError:Javaスタックスペース。最も一般的な例は再帰です。デモテストの再帰的な例を作成しますか?


image.png


プログラムカウンター


プログラムカウンタもスレッド専用です。プログラムのマルチスレッド実行は、CPU割り当てタイムスライスの実行に依存します。簡単な図を描いて、マルチスレッドがCPUタイムスライスをどのように使用するかを確認します。次の図に示すように、スレッド0とスレッド1はcpuタイムスライスを割り当ててプログラムを交互に実行します。スレッド0が最初にタイムスライスを取得すると仮定すると、CPUはタイムスライスが使い果たされた後、再びスレッド1にタイムスライスを割り当てます。スレッド1が実行された後、これはタイムスライスがスレッド0に戻って実行されるとき、問題は、スレッド0が最後にどこで実行されたかということです。コードは何行ありますか?そのコード行は実行されましたか?このとき、プログラムカウンタが遊びに来て、プログラムカウンタはセーブの実行シーン操作の次の再開を促進する、スレッドを。これが、プログラムカウンタがスレッド専用である理由です。

image.png



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


ネイティブメソッドスタックはあまり導入されません。スタック構造と同様に、独立した領域ですが、ネイティブメソッドに対応します。


ダイレクトメモリ


直接メモリは、JVMメモリ以外のメモリから独立しており、NIOインターフェイスと直接対話できます。NIOインターフェイスはメモリを頻繁に操作します。JVM管理に配置すると、間違いなくJVMのオーバーヘッドが増加します。したがって、この部分は個別に提案されます。データはメモリによって直接操作されます。JVMと比較すると、高速であり、プログラムのパフォーマンスが明らかに向上します。



メモリ割り当てパフォーマンスの最適化-エスケープ分析


その前に、キーワードnewが表示されている限り、オブジェクトはヒープに割り当てられている必要があると述べました。ケースを見てみましょう。

/ **
 * @author:jiaolian
 * @date:2021-03-1016:10に作成
 * @description:エスケープ分析テスト
 * @によって変更:
 *公式アカウント:電話
 * /
パブリッククラスEscapeTest {

    //プライベート静的オブジェクトオブジェクト;
    public static void alloc(){
        //オブジェクトは、エスケープオブジェクトではなく、サイズが16kに相当します
        // object = new Object();
        オブジェクトobject = new Object();
    }

    public static void main(String [] args)throws InterruptedException {
        // 10億倍のメモリ
        long begin = System.currentTimeMillis();
        for(int i = 0; i <10000000; i ++){
            alloc();
        }
        long end = System.currentTimeMillis();
        System.out.println( "time:" +(end-begin));
    }
}

上記のコードのように、メイン関数の新しいオブジェクトに対してforループを1億回使用します。オブジェクトは16kです。GBデータがあると概算されます。このとき、JVMパラメーター-XXを手動で構成します。 :+ PrintGC -Xmx10M -XX:+ DoEscapeAnalysis; GC情報を出力するように設定すると、デフォルトの最大ヒープメモリは10Mになります。

  1. -XX:+ PrintGCコンソールがGC情報を出力することを示します。
  2. -Xmx10M最大ヒープメモリを10Mに設定します。
  3. -XX:+ DoEscapeAnalysisエスケープ分析を有効にますデフォルトで有効になっています)。

プログラムを実行すると、印刷結果を下図のように表示します。合計3つのGC実行されましたが、質問があるかもしれません10MのヒープメモリはGBデータの影響に対応する必要がありますが、なぜN GCが必要なのですか、なぜ3つのGCしか必要ないのですか?-XX場合:- DoEscapeAnalysis近いエスケープ分析、GCは何千回も発生する可能性があります。実行時間も3ミリ秒から1000ミリ秒以上に増加しました。これは、非エスケープオブジェクトが新しく構築されたヒープ上に構築されているのではなく、スタック上に構築されていることを示していますそうすることの利点:プログラムGCの実行回数と実行時間の観点から、プログラム操作の効率が向上します。

image.png

  • 原因分析:

上記のケースコードのalloc()メソッドを確認します。メソッド内のObject object = new Object();オブジェクトはローカル変数です。新しい作成が行われるたびに、次のサイクルで作成されます。最後に作成されたオブジェクトがポップされます。スタックから外れ、参照されているオブジェクト。指定されたオブジェクトは無効になり、無効なオブジェクトはGCによって再利用されます。エスケープ分析をオンにすると、new Object()によって作成されたオブジェクトはヒープに割り当てられませんが、スタックに配置されます。これは、JVMがエスケープ分析を通じてメモリを最適化する方法です。それについて考えると、プライベート静的オブジェクトオブジェクト;コメントを手放した場合、オブジェクトは引き続き非エスケープオブジェクトになりますか?

注:エスケープオブジェクトはスタックにスペースを割り当てることができません!

これまでに、エスケープ分析をより明確に理解する必要があると思います


総括する


さて、私は書くのに少しうんざりしています。私は不完全で、まだ修正が必要なことがたくさんあります。修正してコメントしていただければ幸いです。よろしければ、気に入って注意してください。注意点、迷子にならないでください、私は[練習と呼ばれる]公開番号であり、練習中にマイクロシグナル[jiaolian123abc]が彼らに話しました。

image.png


おすすめ

転載: blog.51cto.com/14883474/2656420