현재 위치 - 회사기업대전 - 중국 기업 정보 - jvm 가비지 수집기

jvm 가비지 수집기

JVM 의 CMS, G1 가비지 수집기에서 사용하는 가비지 수집 알고리즘은 3 색 표기법입니다.

3 색 표기법은 오브젝트의 색상을 검은색, 회색, 흰색, 세 가지 색상으로 나눕니다.

문제:

부동 쓰레기: 동시 태그 지정 중 이미 검은색이나 회색으로 표시된 객체가 갑자기 쓰레기가 된 경우 이 객체는 흰색이 아니면 지워지지 않으며 태그를 다시 지정하거나 GC 루트에서 찾을 수 없습니다

객체 누출 문제 (필요한 객체 재활용): 비즈니스 스레드는 동시에 태그 지정 중 스캔되지 않은 흰색 객체 분리 참조를 가비지 (참조 제거) 로 만들고 검은색 객체는 해당 객체를 참조합니다 (참조 추가) (이 두 개는 우선순위를 매길 수 있음). 검은색 개체의 의미는 속성이 이미 표시되어 있고, 태그를 다시 지정해도 검은색 개체에서 찾을 수 없기 때문에, 이 개체는 프로그램에 필요하지만 GC 에 의해 회수되어야 하기 때문에 시스템에 문제가 발생할 수 있습니다. CMS 와 G1, 두 가지 회수기는 모두 3 색 표기법을 사용할 때 이러한 문제를 해결하기 위해 몇 가지 조치를 취하고, CMS 는 참조 링크 추가를 처리합니다.

JVM 가상 시스템에서 이 알고리즘을 사용하는 두 가지 일반적인 가비지 수집기가 있습니다.

CMS (concurrent mark sweep)

CMS, 예

하지만 CMS 는 많은 사소한 문제로 인해 거의 사용되지 않고 있습니다.

증분 업데이트

누출 문제를 해결할 때 CMS 는 Increment Update 방법을 사용하여

를 수행합니다

그러나 그럼에도 불구하고 여전히 누수 문제가 있습니다.

회색 개체가 GC 스레드에 의해 재활용되고 있을 때 이미 표시된 속성이 흰색 개체 (쓰레기)

를 가리킬 때 모든 속성 태그가 끝났다고 생각하고, 이 회색 객체를 검은색으로 표시하고, 다시 참조되는 흰색 객체는

로 표시할 수 없습니다. CMS 는 이 결함을 제외하고는 두 가지 더 치명적인 결함을 가지고 있습니다.

솔루션: map 사용 CMS 를 사용하여 메모리를 동시에 정리하면 OOM 문제가 발생할 수 있습니다. Serial Old GC 를 수행해야 합니다. Serial Old 는 단일 스레드 가비지 수집이며 비효율적입니다.

솔루션: CMS GC 를 트리거하는 임계값을 낮추면 부동 쓰레기가 오래된 시대를 차지하기가 쉽지 않습니다

논리적 분할은 여전히 존재합니다.

사전 지식-카드 테이블 (다양한 가비지 수집기 포함)

YoungGC 를 진행하는 동안 한 개체가 참조되는지 여부를 처리하는 과정에서 전체 Old 영역을 스캔해야 하기 때문에 JVM 이 설계됐다 카드에있는 객체에 Young 영역을 가리키는 참조가 있으면 dirty Card 로 표시하고 다음에 YoungGC 가 필요할 때 Dirty Card 만 스캔하면 됩니다.

Card Table 은 기본 데이터 구조에서 Bit Map 으로 구현됩니다.

cset (collection set)

SATB (snapshot at the beginning)

;

그리고 마지막 G1 에서는 모든 쓰레기 수거를 선택하는 것이 아니라 Region 의 쓰레기 양에 따라 재활용 가치 (재활용된 쓰레기와 회수된 STW 시간의 추정치) 를 결정하고 하나 이상의 Region 을 CSet 에 배치한 다음 이들 Region 의 생존 객체를 압축하여 새 Region 에 복사합니다

질문: G1 은 전체 GC 를 진행할 예정입니까?

예, 메모리가 가득 차면 전체 GC 가 진행됩니다. JDK10 이전의 풀 GC 는 단일 스레드이므로 G1 을 사용하려면 풀 GC 생성을 피해야 합니다.

솔루션:

메모리 증가

CPU 성능 향상, GC 재활용 속도 향상, 개체 증가 속도가 재활용 속도를 따라잡지 못하면 Full GC 는 피할 수 있습니다.

G1 의 첫 번째 paper (부록 1) 가 2004 년에 발표되고 2012 년에야 japer 에 존재하도록 Mixed GC 가 트리거되는 임계값을 낮췄습니다 (기본값 45)

G1 의 첫 번째 paper (부록 1) Oracle government 는 CMS 대신 jdk9 에서 G1 을 기본 가비지 수집기로 바꿀 계획입니다. 왜 Oracle 은 G1 을 적극 추천해야 합니까? G1 의 장점은 무엇입니까?

첫째, G1 의 설계 원칙은 간단하고 실행 가능한 성능 튜닝

개발자는

여기서-xx:+useG1gc 는 G1 가비지 수집기 열기입니다 튜닝이 필요한 경우 메모리 크기가 일정한 경우 최대 일시 중지 시간만 수정하면 됩니다.

둘째, G1 은 신생대, 노년기의 물리적 공간 구분을 취소했다.

이렇게 하면 각 세대의 메모리가 충분한지 걱정할 필요 없이 각 세대를 별도의 공간으로 설정할 수 있습니다.

대신 G1 알고리즘은 힙을 여러 영역 (Region) 으로 나누고 여전히 세대 수집기에 속합니다. 그러나 이러한 영역의 일부에는 신생대가 포함되어 있으며, 신세대 가비지 수집은 여전히 모든 응용 프로그램 스레드를 일시 중지하여 기존 개체를 오래된 시대나 Survivor 공간으로 복사합니다.

이전 시대도 여러 영역으로 나뉘어 G1 수집기는 한 영역에서 다른 영역으로 객체를 복사하여 정리 작업을 완료했습니다. 즉, G1 은 정상적인 처리 과정에서 힙 압축 (최소한 부분 힙 압축) 을 완료하여 CMS 메모리 조각 문제가 발생하지 않도록 합니다.

G1 에는 Humongous 영역이라는 특별한 영역이 있습니다. 개체가 파티션 용량 50 이상을 차지하는 경우 G1 수집기는 이를 거대한 개체로 간주합니다. 이러한 거대한 개체는 기본적으로 노년기에 직접 할당되지만 단기간에 존재하는 거대한 객체라면 가비지 수집기에 부정적인 영향을 미칠 수 있습니다. 이 문제를 해결하기 위해 G1 은 거대한 개체를 전문적으로 보관하는 Humongous 구역을 나누었다. H 구역에 다음 거대한 개체가 들어가지 않으면 G1 은 저장할 연속 H 구역을 찾습니다. 연속 H 구역을 찾기 위해 때때로 풀 GC 를 시작해야 할 때가 있다.

PS: 자바 8 에서는 영구도 일반 힙 메모리 공간으로 옮겨져 메타 공간으로 바뀌었다.

객체 할당 정책

큰 객체 할당에 대해 이야기할 때 객체의 할당 전략에 대해 이야기해야 합니다. 세 단계로 나뉩니다.

TLAB 공간에서 할당할 수 없는 개체에 대해 JVM 은 Eden 공간에서 할당을 시도합니다. Eden 공간이 이 개체를 수용할 수 없는 경우 이전 시대에만 공간을 할당할 수 있습니다.

마지막으로 G1 은 두 가지 GC 모드, Young GC 와 Mixed GC 를 제공하며 둘 다 STW (stop the world) 를 제공합니다. 이 두 가지 모드를 각각 소개하겠습니다.

Young GC 는 주로 Eden 구역의 GC 를 수행하며 Eden 공간이 모두 소모될 때 트리거됩니다. 이 경우 Eden 공간의 데이터는 Survivor 공간으로 이동하고, Survivor 공간이 부족하면 Eden 공간의 일부 데이터가 바로 노년 세대 공간으로 승격됩니다. Survivor zone 의 데이터는 새로운 Survivor zone 으로 이동하며 일부 데이터는 오래된 공간으로 승격됩니다. 결국 Eden 공간의 데이터가 비어 있고 GC 가 작동을 멈추고 응용 프로그램 스레드가 계속 실행됩니다.

이 시점에서 우리는 한 가지 질문을 고려해야 한다. 만약 GC 신생대 개체만 있다면, 우리는 어떻게 모든 루트 개체를 찾을 수 있을까? 오래된 시대의 모든 대상이 뿌리입니까? 이렇게 스캔하는 데는 많은 시간이 걸릴 것이다. 그래서 G1 은 RSet 의 개념을 도입했습니다. 전체 이름은 Remembered Set 이며, heap 영역 내의 객체 참조를 추적하는 데 사용됩니다.

CMS 에도 RSet 개념이 있습니다. 이전 시대에는 신생대에 대한 참조를 기록하는 영역이 있었습니다. 이것은 point-out 입니다. Young GC 에서 루트를 스캔할 때, 오래된 시대 전체를 스캔하지 않고 이 영역만 스캔하면 됩니다. (존 F. 케네디, Northern Exposure (미국 TV 드라마), 예술명언)

그러나 G1 에서는 point-out 이 사용되지 않습니다. 파티션이 너무 작고 파티션 수가 너무 많기 때문입니다. point-out 을 사용하면 많은 스캔 낭비가 발생할 수 있으며 GC 를 전혀 필요로 하지 않는 일부 파티션 참조도 스캔됩니다. 그래서 G1 에서는 point-in 을 사용하여 해결합니다. Point-in 은 현재 파티션의 객체를 참조하는 파티션을 의미합니다. 이렇게 하면 이러한 오브젝트를 루트로만 스캔하여 잘못된 스캔을 피할 수 있습니다.

신생대가 여러 개 있기 때문에, 우리는 신생대 사이에 인용문을 기록해야 합니까? 이것은 불필요하다. 왜냐하면 GC 마다 모든 신생대가 스캔되기 때문이다. 따라서 노년대와 신생대 사이의 인용만 기록하면 된다.

참조할 객체가 많은 경우 할당자는 각 참조를 처리해야 하며 할당자 오버헤드 문제를 해결하기 위해 G1 에 또 다른 개념인 카드 테이블 (Card Table) 이 도입되었습니다. Card Table 은 파티션을 카드라고 하는 고정된 크기의 연속 영역으로 논리적으로 나눕니다. 카드는 일반적으로 128 바이트에서 512 바이트 사이로 작습니다. Card Table 은 일반적으로 Card 의 인덱스 (배열 아래 첨자) 로 각 분할 영역의 공간 주소를 식별하는 바이트 배열입니다. 기본적으로 모든 카드는 참조되지 않습니다. 주소 공간이 참조될 때 이 주소 공간에 해당하는 배열 인덱스의 값은 "0" 으로 표시됩니다. 즉, 더티 참조로 표시되고 RSet 은 이 배열의 아래 첨자를 기록합니다. 일반적으로 이 RSet 은 실제로 Hash Table 이고, 키는 다른 Region 의 시작 주소이고, Value 는 Card Table 의 Index 인 컬렉션입니다.

Young GC 단계:

Mix GC 는 정상적인 신생대 가비지 수집뿐만 아니라 일부 백그라운드 스캔 스레드 표시의 오래된 시대 파티션도 재활용합니다.

GC 단계는 2 단계:

global concurrent marking)

생존 객체 복사 (evacual 글로벌 컨커런트 마킹은 어떤 과정을 거쳤나요?

G1 GC 에서는 주로 Mixed GC 에 태그 지정 서비스를 제공하는 것이지 GC 프로세스의 필수 부분이 아닙니다. Global concurrent marking 실행 프로세스는

초기 마크 (STW)

이 단계에서 G1 GC 가 루트에 태그를 지정하는 5 단계로 나뉩니다 이 단계는 일반 (STW) 젊은 세대 가비지 수집과 밀접한 관련이 있다.

루트 영역 스캔

g1gc 는 초기에 표시된 생존 영역에서 이전 시대에 대한 참조를 스캔하고 참조된 객체를 표시합니다. 이 단계는 어플리케이션 (STW 아님) 과 동시에 실행되며, 이 단계가 완료될 때까지 다음 STW 젊은 세대 가비지 수집을 시작할 수 없습니다.

동시 표시

g1gc 는 힙 전체에서 액세스 가능한 (생존) 객체를 찾습니다. 이 단계는 애플리케이션과 동시에 실행되며 STW 청소년 가비지 수집 중단

최종 표시 (Remark, STW)

는 STW 재활용으로 표시 주기를 완료하는 데 도움이 됩니다. G1 GC 는 SATB 버퍼를 비우고 액세스되지 않은 생존 개체를 추적하고 참조 처리를 수행합니다.

쓰레기 제거 (Cleanup, STW)

이 마지막 단계에서 G1 GC 는 통계 및 RSet 정화 STW 작업을 수행합니다. 통계 기간 동안 G1 GC 는 완전 유휴 영역과 혼합 가비지 회수가 가능한 영역을 식별합니다. 정리 단계에서는 빈 영역을 재설정하여 사용 가능한 목록으로 반환할 때 부분 동시성이 발생합니다.

동시 태그를 언급하면서 동시 태그의 3 색 태그 알고리즘을 이해해야 합니다.

추적식 회수기를 설명하는 유용한 방법으로 회수기의 정확성을 추론할 수 있습니다. 먼저 객체를 세 가지 유형으로 나눕니다.

루트 오브젝트는 검은색으로, 하위 오브젝트는 회색으로 설정됩니다.

회색으로 계속 이동하면서 스윕된 하위 오브젝트의 오브젝트를 검은색으로 설정합니다.

도달 가능한 모든 개체를 트래버스하면 도달 가능한 모든 개체가 검은색으로 바뀝니다. 도달 할 수없는 객체는 흰색이며 청소해야합니다.

보기 좋지만 태그 지정 중에 애플리케이션이 실행 중이면 객체 포인터가 변경될 수 있습니다. 이 경우 객체 손실 문제

가비지 수집기가

를 스캔할 때 애플리케이션이

이렇게 하는 상황을 살펴봅니다 개체의 상태 다이어그램이 다음과 같이 변경됩니다.

가비지 수집기가 스캔을 다시 표시하면 다음과 같이 표시됩니다.

분명히 이 시점에서 C 는 흰색이며, 쓰레기를 청소해야 한다고 생각하는 것은 무리입니다. 그렇다면 응용 프로그램이 실행 중일 때 GC 태그 객체가 손실되지 않도록 어떻게 보장할 수 있을까요? 다음 2 가지 방법을 사용할 수 있습니다.

삽입 시 객체 기록

삭제 시 객체 기록

CMS 및 G1 에 해당하는 두 가지 다른 구현 방법:

<; 삽입시 기록됩니다.

G1 에서는 STAB(snapshot-at-the-beginning) 방식을 사용하여 삭제 시 모든 객체를 기록합니다.

< 글로벌 동시 플래그가 완료되면 어느 시점에서 Mix GC 가 시작됩니다. 이러한 가비지 수집을 "혼합" 이라고 하는 이유는 정상적인 신생대 가비지 수집뿐만 아니라 일부 백그라운드 스캔 스레드 표시의 파티션도 회수하기 때문입니다. 혼합 가비지 수집은 다음과 같습니다.

혼합 GC 도 사용되는 복제 정리 전략이며 GC 가 완료되면 공간이 다시 확보됩니다.

이에 따라 혼합형 GC 는 일단락됐다. 다음 섹션에서는 튜닝 연습에 대해 설명합니다.

MaxGCPauseMillis 튜닝

이전에 GC 사용에 대해 설명한 가장 기본적인 매개 변수:

처음 두 매개 변수는 모두 잘 이해하고, 다음 MaxGCPauseMillis 이 매개변수는 문자 그대로 허용된 GC 의 최대 일시 중지 시간입니다.

G1 은 GC 가 일시 중지될 때마다 설정된 MaxGCPauseMillis 범위 내에 있도록 합니다. 그럼 G1 은 어떻게 최대 일시 중지 시간을 달성할 수 있을까요? 이것은 또 다른 개념인 CSet(collection set) 를 포함한다. 가비지 수집기에서 수집된 영역 모음을 의미합니다.

Young GC: 모든 신생대 region 을 선택합니다. 신세대 region 수를 제어하여 young GC 의 오버헤드를 제어합니다.

Mixed GC: 모든 신생대 region 을 선정하고 global concurrent marking 통계를 기준으로 수익이 높은 여러 오래된 region 을 선정했습니다. 사용자 지정 오버헤드 목표 범위 내에서 가능한 한 수익이 높은 이전 시대 region 을 선택합니다.

이를 이해한 후 최대 일시 중지 시간을 설정하면 됩니다. 우선, 우리가 용인할 수 있는 최대 일시 중지 시간은 한계가 있으며, 우리는 이 한도 내에서 설정해야 한다. 그런데 설정해야 할 값은 어떻게 되나요? 우리는 처리량과 MaxGCPauseMillis 사이에 균형을 맞춰야 한다. MaxGCPauseMillis 설정이 너무 작으면 GC 가 빈번하고 처리량이 떨어집니다. MaxGCPauseMillis 를 너무 크게 설정하면 응용프로그램 일시 중지 시간이 길어집니다. G1 의 기본 일시 중지 시간은 200 밀리초입니다. 여기서 시작하여 적절한 시간을 조정할 수 있습니다.

기타 튜닝 매개 변수

-Xmn 옵션 사용 금지 또는-xx: newratio 와 같은 기타 관련 옵션을 사용하여 젊은 세대 크기를 명시적으로 설정합니다. 젊은 세대의 크기를 고정하면 일시 중지 시간 목표를 덮어쓸 수 있습니다.

전체 GC 트리거

G1 이 전체 GC 를 트리거하는 경우도 있는데, 이 경우 G1 은 직렬 collector 를 사용하여 쓰레기 정리 작업을 완료합니다. 단일 스레드만 사용하여 GC 작업을 완료하고 GC 일시 중지 시간은 초 수준에 도달합니다. 전체 앱은 가사상태에 처해 있어 어떤 요청도 처리할 수 없다. 우리 프로그램은 당연히 이런 것을 보고 싶지 않다. 그럼 풀GC 는 어떤 일이 일어날까요?

동시작업 모드 실패

G1 은 태그 주기를 시작하지만, Mix GC 이전 시대가 채워지고 G1 은 태그 주기를 포기합니다. 이 경우 힙 크기를 늘리거나 주기를 조정해야 합니다 (예: 스레드 수 증가-xx: concgcthreads 등).

승진 실패 또는 대피 실패

G1 GC 진행 중 생존 또는 승진 대상자를 위한 메모리가 부족해 전체 GC 를 트리거했습니다. 로그에서 (to-space exhausted) 또는 (to-space overflow) 를 볼 수 있습니다. 이 문제를 해결하려면

거대한 객체 할당 실패

거대한 객체가 할당할 적절한 공간을 찾을 수 없을 때 전체 GC 를 시작하여 공간을 확보합니다. 이 경우 많은 수의 거대한 오브젝트를 할당하거나 메모리를 늘리거나-xx: G1 heapregionsize 를 늘려 거대한 오브젝트가 더 이상 거대한 오브젝트가 되지 않도록 해야 합니다.

편폭이 제한되어 있어 G1 에는 아직 많은 튜닝 관행이 있어 여기에 일일이 열거되지 않아 평소 실천에서 천천히 탐구할 수 있습니다. 마지막으로, Java 9 가 공식적으로 발표될 것으로 기대하고 있습니다. G1 을 기본적으로 가비지 수집기로 사용하는 Java 성능이 다시 향상되지 않을까요?

G1 프로세싱은 기존의 가비지 수집 전략과는 달리 모든 메모리를 하위 영역으로 나누는 것이 관건이다.

요약

G1 은 메모리 집약형 어플리케이션뿐만 아니라 튜닝 작업도 단순화하는 매우 우수한 가비지 수집기입니다. 주요 매개변수 초기 및 최대 힙 공간과 최대 허용 GC 일시 중지 목표를 통해 좋은 성능을 얻을 수 있습니다. 이와 함께 G1 은 메모리 공간 낭비가 높은 것을 볼 수 있지만 * * 먼저 가비지 (Garbage First) 의 설계 원칙을 수집하면 기한이 지난 개체를 제때에 찾아 메모리 점유를 합리적인 수준으로 유지할 수 있습니다.

참조 링크:

/post/6859931488352370702

/QQ _ 39276448/

copyright 2024회사기업대전