Java Virtual Machine-세대 별 GC

대부분의 JVM은 힙을 3 세대로 나눕니다. the young generation (YG), the old generation (OG) and permanent generation (also called tenured generation). 그러한 생각의 이유는 무엇입니까?

경험적 연구에 따르면 생성 된 대부분의 물체는 수명이 매우 짧습니다.

출처

https://www.oracle.com

시간이 지남에 따라 점점 더 많은 객체가 할당됨을 알 수 있듯이 살아남는 바이트 수가 줄어 듭니다 (일반적으로). Java 객체는 사망률이 높습니다.

간단한 예를 살펴 보겠습니다. Java의 String 클래스는 변경할 수 없습니다. 즉, String 개체의 내용을 변경할 때마다 새 개체를 모두 만들어야합니다. 아래 코드와 같이 루프에서 문자열을 1000 번 변경했다고 가정 해 보겠습니다.

String str = “G11 GC”;

for(int i = 0 ; i < 1000; i++) {
   str = str + String.valueOf(i);
}

각 루프에서 새 문자열 객체를 생성하고 이전 반복 중에 생성 된 문자열은 쓸모 없게됩니다 (즉, 참조에 의해 참조되지 않음). 해당 객체의 수명은 한 번의 반복 일뿐입니다. GC에서 금방 수집합니다. 이러한 단기 개체는 힙의 젊은 세대 영역에 보관됩니다. 젊은 세대의 개체를 수집하는 과정을 마이너 가비지 수집이라고하며 항상 '세상을 멈추는'일시 중지를 유발합니다.

젊은 세대가 꽉 차면 GC는 사소한 가비지 수집을 수행합니다. 죽은 개체는 폐기되고 살아있는 개체는 이전 세대로 이동됩니다. 이 프로세스 중에 애플리케이션 스레드가 중지됩니다.

여기에서 이러한 세대 설계가 제공하는 이점을 확인할 수 있습니다. 젊은 세대는 힙의 작은 부분 일 뿐이며 빠르게 채워집니다. 그러나 처리하는 데 걸리는 시간은 전체 힙을 처리하는 데 걸리는 시간보다 훨씬 적습니다. 따라서이 경우 '세계 중지'일시 중지는 더 자주 발생하지만 훨씬 짧습니다. 더 자주 멈출 수 있더라도 항상 더 긴 일시 중지보다 짧은 일시 중지를 목표로해야합니다. 이 튜토리얼의 뒷부분에서 자세히 설명하겠습니다.

젊은 세대는 두 개의 공간으로 나뉩니다. eden and survivor space. 에덴 수집 중에 살아남은 물체는 생존자 공간으로 이동하고, 생존자 공간에서 살아남은 자들은 구세대로 이동합니다. 젊은 세대는 수집되는 동안 압축됩니다.

개체가 구세대로 이동함에 따라 결국 채워지고 수집 및 압축되어야합니다. 다른 알고리즘은 이에 대해 다른 접근 방식을 취합니다. 그들 중 일부는 애플리케이션 스레드를 중지하고 (이는 이전 세대가 젊은 세대에 비해 상당히 크기 때문에 긴 '세계 중지'일시 중지로 이어짐), 일부는 애플리케이션 스레드가 계속 실행되는 동안 동시에 수행합니다. 이 프로세스를 전체 GC라고합니다. 그러한 두 수집가는CMS and G1.

이제 이러한 알고리즘을 자세히 분석해 보겠습니다.

직렬 GC

클라이언트 클래스 머신 (단일 프로세서 머신 또는 32b JVM, Windows)의 기본 GC입니다. 일반적으로 GC는 다중 스레드가 많지만 직렬 GC는 그렇지 않습니다. 힙을 처리하는 단일 스레드가 있으며 마이너 GC 또는 메이저 GC를 수행 할 때마다 애플리케이션 스레드를 중지합니다. 플래그를 지정하여 JVM에이 GC를 사용하도록 명령 할 수 있습니다.-XX:+UseSerialGC. 다른 알고리즘을 사용하려면 알고리즘 이름을 지정하십시오. 이전 세대는 주요 GC 중에 완전히 압축됩니다.

처리량 GC

이 GC는 64b JVM 및 다중 CPU 시스템에서 기본값입니다. 직렬 GC와 달리 여러 스레드를 사용하여 젊은 세대와 이전 세대를 처리합니다. 이 때문에 GC는parallel collector. 플래그를 사용하여 JVM에이 수집기를 사용하도록 명령 할 수 있습니다.-XX:+UseParallelOldGC 또는 -XX:+UseParallelGC(JDK 8 이상). 애플리케이션 스레드는 메이저 또는 마이너 가비지 콜렉션을 수행하는 동안 중지됩니다. 직렬 수집기와 마찬가지로 주요 GC 중에 젊은 세대를 완전히 압축합니다.

처리량 GC는 YG와 OG를 수집합니다. 에덴이 가득 차면 컬렉터는 라이브 오브젝트를 OG 또는 생존 공간 중 하나로 배출합니다 (아래 다이어그램의 SS0 및 SS1). 죽은 물체는 그들이 차지한 공간을 확보하기 위해 폐기됩니다.

YG의 GC 이전

YG의 GC 이후

전체 GC 동안 처리량 수집기는 전체 YG, SS0 및 SS1을 비 웁니다. 작업 후 OG에는 라이브 오브젝트 만 포함됩니다. 위의 두 수집기는 힙을 처리하는 동안 응용 프로그램 스레드를 중지합니다. 이는 주요 GC 중에 '세계를 멈추는'긴 일시 중지를 의미합니다. 다음 두 알고리즘은 더 많은 하드웨어 리소스를 사용하여이를 제거하는 것을 목표로합니다.

CMS 수집기

'동시 마크 스윕'을 의미합니다. 그 기능은 백그라운드 스레드를 사용하여 이전 세대를 주기적으로 스캔하고 죽은 개체를 제거하는 것입니다. 그러나 마이너 GC 중에 애플리케이션 스레드가 중지됩니다. 그러나 일시 중지는 매우 적습니다. 이것은 CMS를 낮은 일시 중지 수집기로 만듭니다.

이 콜렉터는 애플리케이션 스레드를 실행하는 동안 힙을 스캔하려면 추가 CPU 시간이 필요합니다. 또한 백그라운드 스레드는 힙을 수집하고 압축을 수행하지 않습니다. 힙이 조각화 될 수 있습니다. 이 과정이 계속되면서 특정 시점이 지나면 CMS는 모든 애플리케이션 스레드를 중지하고 단일 스레드를 사용하여 힙을 압축합니다. 다음 JVM 인수를 사용하여 JVM이 CMS 수집기를 사용하도록 지시하십시오.

“XX:+UseConcMarkSweepGC -XX:+UseParNewGC” CMS 수집기를 사용하도록 지시하는 JVM 인수로.

GC 이전

GC 이후

수집은 동시에 수행됩니다.

G1 GC

이 알고리즘은 힙을 여러 영역으로 나누어 작동합니다. CMS 콜렉터와 마찬가지로 마이너 GC를 수행하는 동안 애플리케이션 스레드를 중지하고 백그라운드 스레드를 사용하여 애플리케이션 스레드를 계속 유지하면서 이전 세대를 처리합니다. 구세대를 지역으로 나누었 기 때문에 객체를 한 지역에서 다른 지역으로 이동하면서 계속 압축합니다. 따라서 조각화가 최소화됩니다. 다음 플래그를 사용할 수 있습니다.XX:+UseG1GC이 알고리즘을 사용하도록 JVM에 지시하십시오. CMS와 마찬가지로 힙을 처리하고 애플리케이션 스레드를 동시에 실행하려면 더 많은 CPU 시간이 필요합니다.

이 알고리즘은 여러 지역으로 나뉘는 더 큰 힙 (> 4G)을 처리하도록 설계되었습니다. 그 지역 중 일부는 젊은 세대를 구성하고 나머지는 노인을 구성합니다. YG는 전통적으로 사용하여 지워집니다. 모든 애플리케이션 스레드가 중지되고 이전 세대 또는 생존자 공간에 여전히 살아있는 모든 개체가 삭제됩니다.

모든 GC 알고리즘은 힙을 YG와 OG로 나누고 STWP를 사용하여 YG를 정리합니다. 이 프로세스는 일반적으로 매우 빠릅니다.