JVMでのGarbage Collector


Javaのような管理言語で開発すれば,開発者が直接動的メモリを管理する必要はない.これにより、開発者の利便性と生産性が向上しますが、不明な場合はメモリを管理するアプリケーションが作成される可能性があります.Javaのダイナミックメモリは、JVMのGarbage Collectorによって管理されます.Garbage Collectorの動作に詳しい方は、以前よりも効率的にアプリケーションのメモリとパフォーマンスを向上させることができると思います.

JVMでのStackとHeap


Javaの変数はデフォルトでStackにロードされ、動的に割り当てられたときにHeapにロードされます.次のコードと画像を見ると分かりやすいです.
import java.util.ArrayList;

public class GarbageCollectorTest {
    public static void main(String[] args) throws Exception {
        int a = 1;
        int b = 2;
        ArrayList<Integer> list = new ArrayList<>();

        list.add(a);
        list.add(b);

        for (Integer integer : list) {
            System.out.println(integer);
        }
    }
}

元のタイプはスタックに格納され、参照タイプはスタック内の実際のメモリのアドレスを指す変数のみがスタックに格納され、実際の値はスタックに割り当てられます.では、ゴミ収集器は何をすべきでしょうか.スタックに参照される変数が1つもない場合、すなわち、アクセス不可能なオブジェクトになると、heapが割り当てたメモリを削除する役割を果たします.

Gabage Collectorプロシージャ


GCは基本的にmark->sweap->圧縮の過程を経ている.GC実行時には、stop-the-world現象が基本的に発生し、GCを実行するスレッドを除き、すべてのスレッドが停止します.GCの理解と使用にはメモリのメリットがありますが、stop-the-world時間を減らすことでパフォーマンスを最適化することも含まれています.heapには以下のスペースがあります.

簡単に言えば、最初にheapにオブジェクトが割り当てられた場合、Eden領域に割り当てられ、Edenが満たされている場合、Minor GCが実行され、Survival 0またはSurvival 1領域に移行する.(Survivalの1つの空間が無条件に空いている)Survival 0または1が満たされている場合、Minor GCが再実行され、別の空のSurvival空間に移動します(移動すると到達不可能なオブジェクトは消去されます).
上記の手順を繰り返し、オブジェクトの内部エージェント値(Minor GC実行時に生存、増加)がある値を超えるとOld領域に移行します.その後、Old領域が満たされている場合は、完全GCを実行し、Old領域をクリアします.JVMの設定は変更できますが、デフォルトのYoungとOld領域の割合は1:2です.これは、Young領域のサイズがOld領域より小さい(Young領域の大部分が消える)という仮定のためです.では、Old領域だらけの完全なGCがあれば、大きなメモリ領域をチェックする時間が長くなり、stop-the-worldは長くなります.したがって,完全GCが発生する回数を減らすことも性能最適化の重要な要因である.
JVMのGCでは、以下の4つのアルゴリズムを使用できます.
  • Serial GC
  • Parallel GC
  • Concurrent Mark Sweap GC
  • G1 GC
  • Serial GC


    単一のCPUを使用し、使用可能なメモリが少ない場合に使用します.前述したGCプロセスを1つのスレッドで全て処理した後に実行する.

    Parallel GC


    GCは、複数のスレッドを使用して実行されます.シリアルGCよりもStop the Worldの方が時間が減ることを期待し、下図を見ると分かりやすいです.

    Concurrent Mark Sweap GC


    CMS GCは段階的にGCプロセスを実行する.図では、オレンジ色のスレッドはStop the Worldで発生する領域であり、緑のスレッドはアプリケーションスレッドがアクティブなときに実行されます.すなわち、上述したGCプロセスは同時であり、Stop the Worldの時間を短縮する.
    ただし、CMS GCでは他のアルゴリズムよりも大きなCPUとメモリが必要であり、長時間実行されるアプリケーションではメモリの断片化が激しくなるため、断片化されたメモリのCompactionをクリーンアップする過程で、stop-the-worldが他のアルゴリズムに比べて必要な時間が長くなる可能性があります.

    G1 GC


    JAVA 9以降では、Garbage 1 CollectorがデフォルトGCに変更され、長期的なマルチプロセッサ環境と大メモリ環境でシステムを最適化しています.G 1 GCは、以前heap全体に対してGCを実行していたのとは異なり、heapのメモリ領域を一定サイズに分割して管理している.

    G 1 GCは、上述したように、連続仮想メモリを一定サイズに分割する.各領域は別々であるが,論理的には以前と同様にEden,Survival,Old領域である.残りの空きスペースはAvailabe/Unsedとみなされ、未使用のスペースとみなされます.
    他のGCと同様に、Minor GCでEdenが満たされている場合、Survivalで長期にわたって生存しているオブジェクトはOld領域に移動し、Availabe/Unused空間に移動します.この空間はEdenまたはSurvivalに変更されます.
    メモリ全体が臨界値に達すると完全GCが生成され、G 1 GCはGarbageが一定値より大きい領域でのみGCが実行される.Garbage 1(first)という名前の理由は、このような動作から来ている.従って、完全GCが発生しても、本当に必要な領域内で統合することができ、GCの実行効率を従来よりも向上させることができる.