Jvmシリーズ:一つのテーマからGCゴミ回収を簡単に分析する


一、概説
暇があれば本をめくったり、基礎点を拾ったりして、心を静めて字を書くようにします.JavaベースのものはどうしてもJVMを思い浮かべますが、JVMといえば、バイトコードのロード、クラスの初期化、メソッドの実行、オブジェクトメモリの割り当てと回収、スレッドとロックメカニズムなど、最も一般的な点を思い浮かべます.まとめて整理するとき、どうしてそれらを少なくすることができますか.しかし、私は方法を変えて、あまり概念(ネット上で検索した)を書かないで、いくつかのコード、例、テーマ、疑問などの面から書きたいと思っています.
二、背景知識
JVMメモリ管理に理解すべき点:メモリ領域の分割、メモリ割り当て、メモリ回収.
  • メモリ領域:メソッド領域、スタック領域、ローカルメソッドスタックなどのいくつかの空間を認識し、スタックの世代別管理を理解する.
  • メモリ割り当て:Javaではスタックとスタックであり、作成オブジェクトはスタック領域にあります.
  • メモリ回収:実戦上最も主要なのはいつ回収(GC)と回収が性能に与える影響をトリガーするかに注目し、学習上は異なる回収開始と回収アルゴリズムを理解することができる.
  • 検証とテストに必要なポイント:一般的な起動パラメータ、GUIクラスツール.
  • 一般的な起動パラメータ:-Xms-Xmx-Xmnなど
  • GUI類ツール:JProfiler(推奨)、JVisualVM、MAT、JMap、JHat.
  • 三、一つのGCテーマ
    1)上記のコードを-Xms 30 m-Xmx 30 m-Xmn 10 m-XX:+UseParallelGCで実行する場合、Minor GCは何回、Full GCは何回実行されますか?2)あなたの結果がどのように出てきたかをそれぞれ説明します.
    public static void main(String[] args) throws Exception{
        List caches=new ArrayList();
        for(int i=0;i<7;i++){
            caches.add(new byte[10241024*3]);
        }
        caches.clear();
        for(int j=0;j<2;j++){
            caches.add(new byte[10241024*3]);
        }
        Thread.sleep(5000);
    }

    まず考えて、忙しく下を見ないでください.もし私の分析が間違っていたら!!まず考えて、忙しく下を見ないでください.もし私の分析が間違っていたら!!まず考えて、忙しく下を見ないでください.もし私の分析が間違っていたら!!
    四、小白式の分析過程
    最初のステップで起動パラメータを分析します.まず、「UseParallelGC」パラメータが表示され、ここでは「Parallel Scavenge+Serial Old」を使用していることを示します.では,回収器のタイプから,スタックの新世代はレプリケーションアルゴリズムに基づくgc(すなわちメモリモデルにはfromとto領域がある)であり,スタックの古い年代はタグ−整理アルゴリズムに基づいていることが分かる.次に、「-Xms 30 m-Xmx 30 m」パラメータが表示され、スタック領域は最大30 Mであり、動的に拡張されないことを示します.最後に「-Xmn 10 m」のパラメータを見ると、新生代領域が10 mであることを示し、デフォルトの7.5:1、すなわちEden 7を用いる.5 M(7680 k)であり、fromおよびto領域はそれぞれ1.25 Mであった.
    第2のステップでは、第1のループi 0(すなわち、i=0で生成されたオブジェクトを表し、その後の法則は同じである)とi 1が直接Eden領域に挿入されることを分析する.Eden領域を優先し、十分に配置されるため、このときEdenは6 m/7.5 mである(両者は使用済み/残りを表す.ここでの6 mは近似値であり、他のjvmオブジェクトなどはメモリを占有するため、詳細には議論しない).
    i 2が来て、Edenエリアに入れると、スペースが足りないことに気づきました.MinorGCをトリガーします.そしてi 2をEdenに置きます.その結果,i 0〜i 1をそのまま古い年代に移行したのは,対象3 mが大きすぎてFrom領域を置くことができなかったためである(前述は1.25 m).このときEden区3 m/7.5 m旧年代6 m/20 mgcのlog-->[PSyoungGen:6451 K->272 K(8960 K)]6451 K->6416 K(29440 K)
    i 3が来て、そのままEdenエリアに入れ続けます.この時Eden区6 m/7.5 mの古い年代6 m/20 m
    i 4が来て、i 2と同じ状況で、Edenが足りないことに気づいた.MinorGCを再起動します.そしてi 4をEdenに置きます.結局i 2~i 3をそのまま古い年代に移行し、i 0とi 1に付き添った.このときEden区3 m/7.5 m旧年代12 m/20 mgcのlog-->[PSyoungGen:6650 K->256 K(8960 K)]12794 K->12544 K(29440 K)
    i 5が来て、引き続きEden区に入れて、この時前のi 4を加えて、Eden区6 m/7.5 m古い年代12 m/20 m
    i 6が来て、前のi 2、i 4の状況と同じように、MinorGCをトリガーしました.そしてi 6をEdenに置きます.結果:i 6はEden,i 0〜i 5の6つは古い年代であった.このときEden区3 m/7.5 m旧年代18 m/20 mgcのlog-->[PSyoungGen:6453 K->224 K(8960 K)]18741 K->18656 K(29440 K)ここではFullGCも1回増えた.gcのlog-->[PSyoungGen:240 K->0 K(8960 K)][PSoldGen:18432 K->18593 K(20480 K)]は、この点を完全に分析できなかったが、gcログは、タグ-アレンジが機能したのではないかと推測し、連続した空間を整理するためだろう.
    ステップ3:cachesが実行されたため.clear(); 宣言前のi 0~i 6の7つのオブジェクトは使用できない(すなわちGC Rootsは達成できない)が、各区に十分なスペースがあるため、プログラムの実行が「GCセキュリティポイント」に達していない限りGCはトリガーされない.
    第4歩:j 0が来て、それは引き続きEden区に置いて、この時まだ回収していないi 6に付き添います.この時Eden区6 m/7.5 mの古い年代18 m/20 m
    j 1が来ると、メモリ管理では新世代も旧世代も申請するスペースが足りないことがわかり、FullGCがトリガーされます.結果:古い年代から使用できないi 0〜i 5をすべて乾かし、j 0を古い年代に移し、新生代のi 6を乾かし、j 1を新生代に入れる.このときEden区3 m/7.5 m旧年代3 m/20 mgcのlog-->[PSyoungGen:6178 K->0 K(8960 K)][PSoldGen:18593 K->3233 K(20480K)]
    五、プログラムを実行することによって、分析を検証する
    上記の手順を実行します.パラメータは、-Xms 30 m-Xmx 30 m-Xmn 10 m-XX:+UseParallelGC-XX:+PrintGCDetailsに-XX:+PrintGCDetailsを加えると、GCのロゴを印刷して前の解析を検証できます.
    ps:異なる仮想マシンバージョンの印刷の出力には多少違いがあります.以下のlogは、sumの1.6です.0_43バージョンで印刷され、無関心な出力を削除します.
    [GC [PSYoungGen: 6451K->320K(8960K)]
    [GC [PSYoungGen: 6698K->240K(8960K)]
    [GC [PSYoungGen: 6437K->240K(8960K)]
    [Full GC [PSYoungGen: 240K->0K(8960K)] [PSOldGen: 18432K->18594K(20480K)] 18672K->18594K(29440K)
    [Full GC [PSYoungGen: 6178K->0K(8960K)] [PSOldGen: 18594K->3234K(20480K)] 24773K->3234K(29440K)
    Heap
    PSYoungGen total 8960K, used 3248K
        >eden space 7680K, 42% used
        >from space 1280K, 0% used
        >to space 1280K, 0% used
    PSOldGen total 20480K, used 3234K
    PSPermGen total 21248K, used 3043K

    六、最後に関連する知識点を補充する
    6.1ヒープ区分管理について
    新生代GC(Minor GC):主に新生代での収集動作である.IBMが調査したことがあるそうで、ほとんどの対象は朝生夕死であるため、MinorGCは非常に頻繁で、速度も比較的速い.旧世代GC(Full GC):旧世代での収集動作を指すが、通常は若い世代のゴミ収集も行われる.
    6.2 GCのいくつかのパラメータの説明
    -Xmxは、JVMの最大使用可能メモリを30 Mに設定します.-XmsはJVM拡張メモリを30 Mに設定します.(この値は通常、-Xmxと同じに設定され、ゴミ回収のたびにJVMにメモリが再割り当てされないようにします)-Xmn:若い世代のサイズを10 mに設定します.(ヒープ全体のサイズ=若いサイズ+古いサイズの永続サイズ:永続世代PermGenは非ヒープで、jconsoleで表示可能)-Xss 128 k:(スレッドごとのスタックサイズを設定)永続世代は、PermSizeとMaxPermSize-XX:+UseParallelGC:ゴミ収集器をパラレル収集器として選択します.
    6.3異なるタイプのプロセッサー
    シリアルプロセッサ:適用データ量が比較的小さい(100 M程度);シングルプロセッサの下で応答時間が要求されないアプリケーション.欠点:小型アプリケーションパラレルプロセッサにしか使用できない:適用「スループットに高い要求がある」,マルチCPU,アプリケーション応答時間に要求のない中・大規模アプリケーション.例:バックグラウンド処理、科学計算.欠点:応用応答時間が比較的に長い同時プロセッサ:「応答時間に高い要求がある」、マルチCPU、応用応答時間に高い要求がある中、大型応用を適用する.例:Webサーバ/アプリケーションサーバ、電気通信交換、統合開発環境.
    6.4その他
    GC Rootsは達成できません:GC回収プロセスは対象が回収できるかどうかを判断する方法で、達成性テストと呼ばれます!gcログの印刷:プログラムの起動時にvmパラメータ-XX:+PrintGCDetailsを追加します.