>  기사  >  Java  >  JVM 메모리 관리------가비지 수집기 개선(가비지 수집기 세계에서 쉽게 플레이할 수 있음)

JVM 메모리 관리------가비지 수집기 개선(가비지 수집기 세계에서 쉽게 플레이할 수 있음)

黄舟
黄舟원래의
2016-12-28 15:51:341124검색

소개

이전 장에서 핫스팟의 가비지 수집기 구현에 대해 논의했습니다. 총 6가지 구현과 6가지 조합이 있습니다. 이번에는 LZ가 이 6명의 수집가 각각의 힘과 이들의 조합의 힘에 대해 논의할 것입니다.
모든 사람이 쉽게 보고 비교할 수 있도록 LZ는 특정 컬렉터를 중심으로 디자인 패턴을 작성할 때 사용하는 방법을 사용하여 이러한 컬렉터를 여러 차원에서 설명하기로 결정했습니다.

클라이언트 모드와 서버 모드

이 장의 내용을 소개하기 전에 JVM의 두 가지 모드에 대해 설명하겠습니다. 하나는 클라이언트 모드이고 다른 하나는 서버 모드입니다. 우리가 일반적으로 개발에 사용하는 모드는 기본적으로 클라이언트 모드입니다. 명령줄 매개변수 -server를 사용하여 서버 모드를 강제로 켤 수도 있습니다. 둘 사이의 가장 큰 차이점은 JVM이 서버에서 많은 최적화를 수행했다는 것입니다. 방법.
서버 모드의 JAVA 애플리케이션은 느리게 시작되지만, 서버 모드의 JVM 최적화로 인해 프로그램을 장시간 실행하면 실행 속도가 점점 더 빨라집니다. 반대로 클라이언트 모드의 JAVA 애플리케이션은 빠르게 시작되지만 장기간 실행하는 데는 적합하지 않습니다. 실행 시간이 길면 서버 모드에 비해 성능이 크게 떨어집니다.

컬렉터에 대한 자세한 설명

먼저 단일 가비지 컬렉터에 대한 관련 내용을 논의하고, 마지막으로 조합 후 각 조합의 특징에 대해 간략하게 이야기하겠습니다.

Serial Garbage Collector

알고리즘: 복사 알고리즘 사용
메모리 영역: 신세대에 맞게 설계
실행 방법: 싱글 스레드, 직렬
실행 프로세스: 신세대 메모리가 충분하지 않으면 먼저 모든 사용자 프로그램을 일시 중지한 다음 GC 스레드를 시작하여 복사 알고리즘을 사용하여 가비지를 수집합니다. 이 과정에서 일부 개체가 이전 세대로 승격될 수 있습니다.
특징: 단일 스레드로 인해 작업 및 전체 GC 각 단계에서 사용자 프로그램을 일시 중지해야 하므로 애플리케이션이 오랫동안 일시 중지되지만 소규모 프로그램에 매우 적합합니다.
적용 가능한 시나리오: 일상적인 개발 및 디버깅 프로그램 사용, 데스크톱 애플리케이션 대화형 프로그램.
열린 매개변수: -XX:+UseSerialGC(클라이언트 모드 기본값)

Serial Old Garbage Collector

여기서는 더 이상 Serial Old Collector에 대한 각 차원의 특성을 나열하지 않습니다. 직렬 수집기와는 다릅니다. 차이점은 이전 세대용으로 설계되었으므로 마킹/조합 알고리즘을 사용한다는 것입니다. 나머지 치수 특성은 Serial Old가 Serial Collector와 완전히 동일합니다.

ParNew Garbage Collector

알고리즘: 복사 알고리즘 사용
메모리 영역: 신세대에 맞게 설계
실행 방법: 멀티 스레드, 병렬
실행 프로세스: 현세대 메모리가 충분하지 않은 경우 먼저 모든 사용자 프로그램을 일시 중지한 다음 여러 GC 스레드를 시작하여 복사 알고리즘을 사용하여 가비지 수집을 병렬로 수행합니다. 이 과정에서 일부 개체가 이전 세대로 승격될 수 있습니다.
특징: 다중 -스레드는 병렬로 실행되는 데 사용되므로 시스템의 코어 프로세서 수에 민감합니다. 최소한 두 개 이상의 프로세서가 필요합니다. 여러 프로세서가 여러 스레드를 엽니다(그러나 스레드 수는 다음을 사용하여 제어할 수 있습니다). -XX:ParallelGCThreads=) 매개변수이므로 다중 코어 및 다중 프로세서 시스템에만 적합합니다. 전체 GC 단계 동안 사용자 프로그램을 일시 중지해야 하지만 다중 스레드 병렬 처리로 인해 너무 긴 일시 중지가 발생하지는 않습니다. 따라서 처리량 측면에서 ParNew는 프로세서가 많을수록 효과가 더 분명합니다. 그러나 이것이 절대적인 것은 아닙니다. 단일 프로세서의 경우 ParNew의 성능은 병렬 실행(예: 동기화)의 오버헤드로 인해 직렬 수집기의 성능보다 낮습니다. 단일 프로세서를 사용하는 경우뿐만 아니라 더 작은 용량의 힙을 사용하는 경우, 두 개의 프로세서를 사용하는 경우에도 ParNew의 성능이 반드시 직렬보다 높지는 않습니다.
적용 가능한 시나리오: 중대형 힙에서 시스템에 하나 이상의 프로세서가 있습니다.
매개 변수 활성화: -XX:+UseParNewGC

병렬 청소 가비지 수집기

이 수집기 ParNew와 거의 동일합니다. 둘 다 차세대를 위해 설계되었으며 복제 알고리즘을 사용하는 병렬 수집기입니다. ParNew와 가장 큰 차이점은 설정 가능한 매개 변수가 다르기 때문에 GC 일시 중지 시간과 처리량을 보다 정확하게 제어할 수 있다는 것입니다.
병렬 청소 수집기에서 제공하는 매개 변수에는 주로 최대 일시 중지 시간 제어(-XX:MaxGCPauseMillis= 사용) 및 처리량 제어(-XX:GCTimeRatio= 사용)가 포함됩니다. 이를 통해 병렬 청소는 처리량 제어를 제공하는 수집기임을 알 수 있습니다.
그러나 최대 일시 중지 시간이 작을수록 좋다거나 처리량이 클수록 좋다고 생각하지 마십시오. 병렬 청소 수집기를 사용할 때 최대 일시 중지 시간, 처리량 및 신규라는 세 가지 주요 성능 지표가 있습니다. 생성 영역의 최소값입니다.
병렬 스캐빈지 컬렉터에는 해당 조정 전략이 있으며, 최대 일시 중지 시간, 처리량, 마지막으로 새로운 세대 영역의 최소값 목표를 달성하는 데 우선순위를 둡니다.
따라서 최대 일시 중지 시간을 너무 작게 설정하면 이기적인 욕구를 충족시키기 위해 전체 처리량과 차세대 크기가 희생됩니다. 손바닥과 손등에는 살이 가득 차 있으니 이렇게 하지 않는 것이 좋습니다. 그러나 병렬 청소에는 병렬 청소 수집기가 메모리 영역 크기 조정을 완전히 인계할 수 있도록 하는 매개변수가 있습니다. 여기에는 이전 세대로의 승격 기간도 포함됩니다(-XX:MaxTenuringThreshold=n을 사용하여 조정할 수 있음). 즉, -XX를 사용합니다. UseAdaptiveSizePolicy는 메모리 영역 크기 적응 정책을 켭니다.
병렬 스캐빈지 컬렉터는 -XX:+UseParallelGC 매개변수를 사용하여 켤 수 있습니다. 이는 서버 모드의 기본 차세대 컬렉터이기도 합니다.

Parallel Old Garbage Collector

Parallel Old와 ParNew 또는 Parallel Scavenge의 관계는 Serial과 Serial Old의 차이는 크지 않지만, Parallel Old는 노년층을 위한 것입니다. 는 현대에 설계된 병렬 수집기이므로 표시/조합 알고리즘을 사용합니다.
Parallel Old 컬렉터의 또 다른 중요한 의미는 Serial Old 외에 병렬 스캐빈지와 함께 작동할 수 있는 유일한 Old Generation 컬렉터라는 것입니다. 따라서 Serial Old가 병렬 스캐빈지의 제어 가능한 처리량에 대한 평판에 영향을 미치는 것을 방지하기 위해 병렬 old는 병렬 청소의 진정한 파트너 역할을 합니다.
-XX:-UseParallelOldGC 매개변수를 사용하여 활성화할 수 있지만 JDK6 이후에는 병렬 청소를 활성화한 후 기본 Old Generation Collector이기도 합니다.

Concurrent Mark Sweep Garbage Collector

Concurrent Mark Sweep(이하 CMS) Collector는 애플리케이션과 GC 스레드를 진정으로 구현하여 함께(고객을 위해, 그리고 함께 반드시 참인 것은 아니며 빠르게 교대로 수집되는 것일 수 있습니다.
CMS는 Old Generation을 위해 설계된 Collector로 Mark/Clear 알고리즘을 사용하며 Old Generation에서 Mark/Clear 알고리즘을 사용하는 유일한 Collector이기도 합니다.
마크/클리어 알고리즘을 사용하는 이유는 4단계로 구분되는 특수한 처리 방식 때문입니다.
1. 초기 마킹: 애플리케이션을 일시 중지하고 살아남은 개체를 빠르게 표시하는 데 필요합니다.
2. 동시 마킹: 애플리케이션을 복원하고 GC 루트를 동시에 추적합니다.
3. 재표시: 애플리케이션을 일시 중지하고 추적에서 누락된 개체를 다시 표시해야 합니다.
4. 동시 삭제: 애플리케이션을 복원하고 표시되지 않은 가비지 개체를 동시에 삭제합니다.
동시 마킹과 동시 클리어의 두 단계에서 주로 나타나는 기존 마크/클리어 알고리즘보다 조금 더 복잡하며, 이 두 단계는 전체 GC 단계에서 시간이 가장 오래 걸리는 단계이기도 합니다. 이 두 가지 스테이지로 인해 애플리케이션과 동시에 스테이지가 실행되므로 CMS 컬렉터로 인한 일시 중지 시간이 매우 짧습니다. 이는 비교적 이해하기 쉽습니다.
단, 단점을 간략하게 언급해야 하는데, 주요 내용은 다음과 같습니다.

1. GC 스레드와 응용 프로그램이 동시에 실행되면 CPU 리소스를 점유하므로 전체 처리량이 감소합니다. 즉, 처리량 지표 측면에서 CMS 수집기는 병렬 청소 수집기보다 약합니다. 여기서 LZ는 Oracle 공식 웹사이트에서 CMS에 대한 설명을 발췌했는데, 여기에는 CMS 성능과 CPU 수 간의 관계가 언급되어 있습니다.
동시 단계 동안 가비지 수집을 위해 하나 이상의 프로세서가 사용되므로 동시 수집기는 일반적으로 단일 프로세서(단일 코어) 시스템에서 어떤 이점도 제공하지 않습니다. 그러나 낮은 일시 중지를 달성할 수 있는 별도의 모드를 사용할 수 있습니다. 프로세서가 1개 또는 2개만 있는 시스템의 경우 자세한 내용은 아래 증분 모드를 참조하세요.

LZ의 영어는 매우 평균적이지만(레벨 4를 통과하지 못했습니다. 수치심, 0.0) 도움을 받아 대략적으로 번역할 수 있습니다. 도구의 의미 이 구절의 의미는 다음과 같습니다.
중국어 요점: 동시 단계의 가비지 수집은 하나 이상의 프로세서를 사용하므로 단일 프로세서에서 동시 수집기를 사용해도 아무런 이점이 없습니다. 그러나 단일 또는 2개의 프로세서 시스템에서 낮은 일시 중지를 효과적으로 달성하는 독립적인 방법이 있습니다. 자세한 내용은 아래 증분 모드를 참조하세요.
분명히 Oracle 문서에서는 단일 프로세서의 경우 동시 수집기가 프로세서 선점으로 인해 성능 저하를 일으킬 것이라고 지적합니다. 마지막으로 증분 모드를 다루는 방법을 제시하고 있는데, "JAVA 가상 머신 심층 이해"라는 책에서는 증분 모드가 권장되지 않는 것으로 정의되어 있다고 지적하고 있습니다. LZ에서 발췌한 공식 서문은 JDK5.0 도입을 기반으로 하고 있으며, "JAVA 가상 머신 심층 이해"라는 책에서는 JDK6.0 버전을 언급하고 있으므로 LZ는 증분 모드가 JDK6에 있는 것으로 잠정적으로 추측합니다. 0 출시 당시에는 폐기되었지만, 이러한 폐기 시기나 버전은 사실 더 이상 중요하지 않습니다.
2. 마크/클리어의 가장 큰 단점은 메모리 조각화가 존재한다는 것입니다. 따라서 JVM에서는 글로벌 GC(full GC) 이후 조각 모음을 수행하기 위해 -XX:+UseCMSCompactAtFullCollection 매개 변수를 제공합니다. 각 글로벌 GC 이후의 조각 모음은 일시 중지 시간에 큰 영향을 미치므로 JVM에서는 -XX:CMSFullGCsBeforeCompaction 매개 변수도 제공하여 여러 글로벌 GC 후 조각 모음.
3. CMS의 마지막 단점은 동시 모드 실패라는 용어와 관련이 있습니다. 이것이 이 용어에 대한 공식적인 설명입니다.
동시 수집기가 종신 세대가 가득 차기 전에 도달할 수 없는 개체의 회수를 완료할 수 없거나 종신 세대의 사용 가능한 여유 공간 블록으로 할당을 충족할 수 없는 경우 애플리케이션이 일시 중지되고 모든 항목을 사용하여 수집이 완료됩니다. 애플리케이션 스레드가 중지되었습니다. 컬렉션을 동시에 완료할 수 없는 것을 동시 모드 실패라고 하며 동시 수집기 매개변수를 조정해야 함을 나타냅니다.
중국어 의미: 이전 세대가 채워지기 전에 동시 수집기를 완료할 수 없는 경우 도달할 수 없는(접근할 수 없는) 객체 재활용 또는 이전 세대의 유효 여유 메모리 공간이 특정 메모리 할당 요청을 충족할 수 없는 경우 애플리케이션이 일시 중지되고 이 일시 중지 기간 동안 애플리케이션이 시작되지 않습니다. 재활용이 완료될 때까지 재개됩니다. 이러한 동시 수집 완료 실패를 동시 모드 실패라고 하며, 이러한 상황이 발생한다는 것은 동시 수집기의 매개변수를 조정해야 함을 의미하기도 합니다.
위의 두 상황은 다소 반복적으로 느껴지네요. Old Generation이 가득 차기 전에 객체 재활용을 완료하지 못해 메모리 할당 요청을 충족하지 못하는 것이 아닌가요?
여기서 LZ가 개인적으로 이해한 바는 Old Generation이 가득 차기 전에 객체 재활용을 완료할 수 없다는 것은 동시 클리어 단계에서 Old Generation이 제때 클리어되지 않아 여유 메모리가 부족하다는 것을 의미한다는 것입니다. 메모리 할당 요청을 충족할 수 없다는 것은 주로 신세대가 Old 세대로 승격될 때 Old 세대의 메모리 조각이 너무 많아 지속적인 메모리가 없어 일부 할당을 충족할 수 없다는 사실을 의미합니다.
실제로 Concurrent 모드가 실패하면 Serial Old가 Global GC(Full GC)를 수행하기 위한 대체 Collector로 사용되기 때문에 Serial Old도 CMS의 '대체'라고 볼 수 있습니다. 당연히 연쇄 구식의 개입으로 인해 큰 휴지 시간이 발생하게 된다.
동시 모드 실패를 최대한 방지하기 위해 -XX:CMSInitiatingOccupancyFraction= 매개변수를 조정하여 이전 세대의 메모리 사용량이 N%에 도달하는지 제어한 다음 동시 모드를 시작할 수 있습니다. 수집가는 오래된 세대를 재활용하기 시작합니다.

조합의 힘

위에서 각 컬렉터의 특징을 간략히 소개했습니다. 아래에서는 일반적으로 사용되지 않는 세 가지 대표적인 조합을 LZ에서 알려드리겠습니다.

serial & serial old

이 조합은 가장 일반적인 조합 중 하나이며 클라이언트 모드의 기본 가비지 수집기 조합이기도 합니다. -XX:+UseSerialGC 매개변수를 사용하여 강제로 설정할 수도 있습니다. 그것을.
구현이 비교적 간단하고 추가적인 스레드 관련 오버헤드(주로 스레드 전환 및 동기화)가 없기 때문에 클라이언트 PC에서 실행되는 소규모 애플리케이션이나 데스크톱 애플리케이션(예: 스윙), 일반적인 개발, 디버깅, 테스트 등도 마찬가지입니다.
위 세 가지 상황은 모두 공통적인 특징을 가지고 있습니다.
1. 모두 PC에서 실행되기 때문에 일반적으로 구성이 너무 높지 않거나 프로세서 수가 너무 많지 않습니다.
2. 위 상황에서는 애플리케이션이 너무 오랫동안 실행되지 않습니다.
3. 규모가 너무 크지 않을 것입니다. 즉, 힙이 상대적으로 작을 것이고, 수집이 더 빨라질 것이며, 일시정지 시간이 더 짧아질 것입니다.

Parallel Scavenge & Parallel Old

이 조합은 결국 우리의 일반적인 개발에는 나타나지 않지만 높은 처리량이 필요한 조합입니다. 높은 일시 정지 시간(일시 정지 시간)이 필요하지 않은 애플리케이션을 위한 선택이며 이 조합은 서버 모드(JDK6 또는 JDK6 이후)의 기본 조합입니다. 물론 -XX:+UseParallelGC 매개변수를 사용하여 강제로 켤 수도 있습니다.
이 조합은 신세대와 구세대 모두에서 병렬 수집을 사용하므로 일시 중지 시간이 짧아지고 시스템의 전체 처리량이 높아집니다. 오랫동안 실행해야 하고 특정 처리량 요구 사항이 있는 일부 백그라운드 프로그램에 적합합니다.
백그라운드에서 실행되는 이러한 프로그램은 다음과 같은 특징을 가지고 있습니다.
1. 시스템 구성은 상대적으로 높으며 일반적으로 최소 4개의 코어(현재 하드웨어 수준 기준)입니다.
2. 처리량 요구 사항이 높거나 특정 금액에 도달해야 합니다.
3. 애플리케이션 실행에 오랜 시간이 걸립니다.
4. 애플리케이션 크기는 크며 일반적으로 중간에서 큰 힙입니다.

ParNew & CMS (Serial Old를 대체)

이 조합은 위의 병렬 조합과 동일하며 일상적인 개발에서는 흔하지 않으며, 응답 시간을 우선으로 합니다. 보다 까다로운 애플리케이션용. 이 조합은 -XX:+UseConcMarkSweepGC 매개변수를 사용하여 활성화해야 합니다.
이 조합은 신세대에서 병렬 컬렉터를 사용하기 때문에 신세대의 GC 속도는 매우 빠르고 Pause 시간은 매우 짧습니다. Young 세대의 GC는 대부분의 가비지 수집 시간 동안 GC 스레드가 애플리케이션과 동시에 실행되므로 일시 중지 시간이 여전히 매우 짧습니다. 오랜 시간 동안 실행해야 하고 해당 시간에 대한 특정 요구 사항이 있는 일부 백그라운드 프로그램에 적합합니다.
백그라운드에서 실행되는 이러한 프로그램의 특성은 병렬 모드의 백그라운드 프로그램과 매우 유사합니다. 차이점은 두 번째 점입니다. ParNew와 CMS의 조합을 사용하는 백그라운드 애플리케이션은 일반적으로 응답 시간에 대한 특정 요구 사항을 갖습니다. 이것이 우리의 웹 애플리케이션입니다.

결론

이번에는 LZ가 각 콜렉터의 특징과 각 조합의 특징을 정리했습니다. 그 외에도 LZ가 여기서 언급하지 않은 조합이 3개 남아 있는데, 그 이유는 이 3개 조합이 특별히 자주 사용되지 않거나, 그럴 수도 있기 때문입니다. 이 세 가지 조합은 모두 다른 느낌을 주고 효과도 별로 좋지 않다고 합니다.
이 기사가 도움이 되기를 바랍니다. 시청해 주셔서 감사합니다.

위 내용은 JVM 메모리 관리------가비지 수집기 개선(가비지 수집기 세계에서 쉽게 플레이할 수 있도록 함)에 대한 내용입니다. 더 많은 관련 내용을 보려면 PHP를 참고하세요. 중국사이트(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.