1. 기본 재활용 알고리즘
1. 참조 카운팅
비교적 오래된 재활용 알고리즘입니다. 원칙은 이 객체에 참조가 있어 개수가 증가하고 참조를 삭제하면 개수가 감소한다는 것입니다. 가비지 수집 중에는 개수가 0인 개체만 수집됩니다. 이 알고리즘의 가장 치명적인 점은 순환 참조 문제를 처리할 수 없다는 것입니다.
2. Mark-Sweep(마크-스윕)
이 알고리즘은 두 단계로 실행됩니다. 첫 번째 단계에서는 참조 루트 노드부터 시작하여 모든 참조 개체를 표시합니다. 두 번째 단계에서는 전체 힙을 순회하고 표시되지 않은 개체를 지웁니다. 이 알고리즘을 사용하려면 전체 애플리케이션을 일시 중지해야 하며 동시에 메모리 조각화가 발생합니다.
3. 복사
이 알고리즘은 메모리 공간을 두 개의 동일한 영역으로 나누고 한 번에 하나만 사용합니다. 가비지 컬렉션 중에는 현재 사용 중인 영역을 순회하고 사용 중인 객체를 다른 영역으로 복사합니다. 이 알고리즘은 매번 사용 중인 개체만 처리하므로 복사 비용이 상대적으로 적습니다. 동시에 복사 후 해당 메모리를 정리할 수 있지만 "조각화" 문제가 발생합니다. 물론 이 알고리즘의 단점도 분명합니다. 즉, 두 배의 메모리 공간이 필요하다는 것입니다.
4. Mark-Compact
이 알고리즘은 "mark-clear" 알고리즘과 "copy" 알고리즘의 장점을 결합합니다. 또한 첫 번째 단계는 루트 노드에서 시작하여 참조된 모든 개체를 표시합니다. 두 번째 단계는 전체 힙을 순회하여 표시되지 않은 개체를 지우고 살아남은 개체를 힙 중 하나로 "압축"하여 순서대로 배출합니다. . 이 알고리즘은 "mark-and-sweep"의 조각화 문제를 방지하고 "복사" 알고리즘의 공간 문제도 방지합니다.
5. 증분 수집(Incremental Collecting)
가비지 수집 알고리즘을 구현합니다. 즉, 애플리케이션이 진행되는 동안 가비지 수집을 수행합니다. JDK5.0의 수집기가 왜 이 알고리즘을 사용하지 않는지 모르겠습니다.
6. 객체 수집
객체 수명주기 분석을 기반으로 한 가비지 수집 알고리즘입니다. 객체를 Young Generation, Old Generation, Persistant Generation으로 나누고, 서로 다른 알고리즘(위 방법 중 하나)을 사용하여 서로 다른 수명주기를 가진 객체를 재활용합니다. 현재 가비지 수집기(J2SE1.2부터 시작)는 모두 이 알고리즘을 사용합니다.
1. Young(젊은 세대)
젊은 세대는 세 가지 영역으로 나누어진다. 하나의 에덴 지역과 두 개의 생존자 지역. 대부분의 객체는 에덴 지역에서 생성됩니다. Eden 영역이 가득 차면 살아남은 개체는 Survivor 영역(둘 중 하나)으로 복사됩니다. 이 Survivor 영역이 가득 차면 이 영역에 남아 있는 개체는 이 Survivor가 사라지면 다른 Survivor 영역으로 복사됩니다. , 가득 차면 첫 번째 생존자 영역에서 복사되어 현재 아직 살아있는 개체가 "Tenured" 영역에 복사됩니다. 주의할 점은 Survivor의 두 영역은 대칭적이며 순차적인 관계가 없기 때문에 Eden에서 복사한 개체와 이전 Survivor에서 복사한 개체가 같은 영역에 동시에 복사될 수 있다는 점입니다. 이전 영역은 생존자가 처음 온 개체에서 복사됩니다. 게다가 생존자 영역 중 하나는 항상 비어 있습니다.
2. Tenured(Old Generation)
늙은 세대는 젊은 세대로부터 살아남은 물건을 보관합니다. 일반적으로 구세대는 수명이 더 긴 개체를 저장합니다.
3. Perm(영구 생성)
정적 파일을 저장하는 데 사용되며 현재는 Java 클래스, 메소드 등이 있습니다. 영구 생성은 가비지 수집에 큰 영향을 미치지 않지만 일부 응용 프로그램은 Hibernate 등과 같은 일부 클래스를 동적으로 생성하거나 호출할 수 있습니다. 이 경우 새로 추가된 클래스를 저장하기 위해 상대적으로 큰 영구 생성 공간을 설정해야 합니다. 작업. 지속적 생성의 크기는 -XX:MaxPermSize=
2. GC 유형
GC에는 Scavenge GC와 Full GC 두 가지 유형이 있습니다.
1.Scavenge GC
일반적으로 Eden에서 새로운 객체가 생성되어 공간 적용에 실패하면 Scavenge GC가 발생하고 힙의 Eden 영역은 GCed, 비생존 객체입니다. 제거되고 나머지 생존 개체는 생존자 영역으로 이동됩니다. 그런 다음 생존자의 두 영역을 구성합니다.
2. Full GC
Young, Tenured, Perm을 포함한 전체 힙을 완료합니다. Full GC는 Scavenge GC보다 속도가 느리므로 Full GC를 최대한 줄여야 합니다. 다음과 같은 이유로 Full GC가 발생할 수 있습니다.
* Tenured가 채워짐
* Perm 필드가 채워짐
* System.gc()가 명시적으로 호출됨
* 힙 필드가 마지막 GC Dynamic 이후에 할당됨 전략 변화
세대별 가비지 수집 프로세스 시연
1.
2.
3.
4.
2. 가비지 컬렉터
현재 컬렉터에는 크게 세 가지 유형이 있습니다. : 직렬 수집기, 병렬 수집기, 동시 수집기.
1. 직렬 수집기
는 단일 스레드를 사용하여 모든 가비지 수집 작업을 처리하므로 다중 스레드 상호 작용이 필요하지 않으므로 더 효율적입니다. 그러나 다중 프로세서의 장점을 이용할 수 없으므로 이 수집기는 단일 프로세서 시스템에 적합합니다. 물론 이 수집기는 데이터 용량이 작은(약 100M) 다중 프로세서 시스템에서도 사용할 수 있습니다. -XX:+UseSerialGC로 활성화할 수 있습니다.
2. 병렬 수집기
1. 젊은 세대에 대해 병렬 가비지 수집을 수행하여 가비지 수집 시간을 줄입니다. 일반적으로 다중 스레드 다중 프로세서 시스템에서 사용됩니다. -XX:+UseParallelGC를 사용하여 엽니다. 병렬 수집기는 J2SE5.0의 6번째 업데이트에서 도입되었으며 Java SE6.0에서 향상되었습니다. 이는 병렬 수집을 위해 이전 세대를 힙할 수 있습니다. 이전 세대가 동시 수집을 사용하지 않는 경우 가비지 수집을 위해 단일 스레드를 사용하므로 확장 기능이 제한됩니다. -XX:+UseParallelOldGC로 엽니다.
2. -XX:ParallelGCThreads=
3. 이 수집기는 다음과 같이 구성할 수 있습니다.
* 최대 가비지 수집 일시 중지: -XX:MaxGCPauseMillis=
* 처리량: 처리량은 가비지 수집 시간과 비가비지 수집 시간의 비율이며 -XX:GCTimeRatio=
3. 동시 수집기
는 대부분의 작업이 동시에 수행되고(애플리케이션이 중지되지 않음) 가비지 수집이 짧은 시간 동안만 일시 중지되도록 보장할 수 있습니다. 이 수집기는 중형 및 고급형에 적합합니다. 높은 응답 시간 요구 사항이 있는 애플리케이션. -XX:+UseConcMarkSweepGC를 사용하여 켜세요.
1. 동시 수집기는 주로 독립적인 가비지 수집 스레드를 사용하여 애플리케이션을 중지하지 않고 도달 가능한 객체를 추적합니다. 각 이전 세대 가비지 수집 주기 동안 동시 수집기는 수집 시작 시 전체 애플리케이션을 잠시 일시 중지하고 수집 중에 다시 일시 중지합니다. 두 번째 일시 중지는 여러 스레드가 동시에 가비지 수집 작업을 수행하는 첫 번째 일시 중지보다 약간 더 길어집니다.
2. 동시 수집기는 짧은 일시 중지 시간 대신 프로세서를 사용합니다. N개의 프로세서가 있는 시스템에서 동시 수집 부분은 재활용을 위해 K/N개의 사용 가능한 프로세서를 사용합니다. 일반적으로 13. 프로세서가 하나만 있는 호스트에서 동시 수집기를 사용하고 증분 모드로 설정하여 일시 중지 시간을 단축합니다.
4. 플로팅 가비지: 애플리케이션이 실행되는 동안 가비지 수집이 수행되므로 가비지 수집이 완료되면 일부 가비지가 생성되어 다음 가비지 수집 주기에 이 가비지를 재활용해야 합니다. . 잃다. 따라서 동시 수집기에는 일반적으로 이러한 부동 쓰레기를 위해 20%의 예약된 공간이 필요합니다.
5. 동시 수집기는 애플리케이션이 실행 중일 때 수집하므로 가비지 수집 중에 프로그램이 사용할 수 있는 충분한 공간이 힙에 있는지 확인해야 합니다. 그렇지 않으면 힙 공간이 가득 차게 됩니다. 가비지 수집이 완료되었습니다. 이 경우 "동시성 모드 실패"가 발생하고 가비지 수집을 위해 전체 애플리케이션이 일시 중지됩니다.
6. 동시 수집 시작: 애플리케이션이 실행되는 동안 동시 수집이 수행되므로 수집이 완료되기 전에 프로그램이 사용할 메모리 공간이 충분한지 확인해야 합니다. 그렇지 않으면 "동시 모드 실패"가 발생합니다. -XX:CMSInitiatingOccupancyFraction=
4. 요약
* 직렬 프로세서:
--적용 가능한 상황: 데이터 볼륨 소형(약 100M), 단일 프로세서에서 실행되고 응답 시간에 대한 요구 사항이 없는 애플리케이션입니다.
--단점: 소규모 애플리케이션에만 사용할 수 있습니다.
* 병렬 프로세서:
--적용 가능한 상황: "처리량에 대한 높은 요구 사항", 다중 CPU가 있고 애플리케이션 응답 시간에 대한 요구 사항이 없는 중대형 애플리케이션 대규모 애플리케이션. 예: 백그라운드 처리, 과학 컴퓨팅.
--단점: 애플리케이션 응답 시간이 더 길어질 수 있음
* 동시 프로세서:
--적용 가능한 상황: "응답 시간에 대한 높은 요구 사항", 다중 CPU, 애플리케이션 응답 시간에 대한 높은 요구 사항 중간 및 대규모 애플리케이션. 예: 웹 서버/응용 서버, 통신 스위칭, 통합 개발 환경.
3. GC의 기본 원리
GC(Garbage Collection)는 JAVA/.NET의 가비지 수집기입니다.
Java는 C++에서 일부 번거롭고 오류가 발생하기 쉬운 부분을 버리고 카운터 개념을 도입했습니다. 그 중 하나가 GC 메커니즘(JAVA에서 차용한 C#)입니다.
프로그래머는 일부에서 문제를 일으키기 쉽습니다. 장소, 잊어버리거나 잘못된 메모리 재활용으로 인해 프로그램이나 시스템이 불안정해지거나 심지어 충돌이 발생할 수 있습니다. Java에서 제공하는 GC 기능은 객체가 자동으로 메모리를 재활용하는 목적을 달성하기 위해 범위를 초과하는지 여부를 자동으로 모니터링할 수 있습니다. 할당된 메모리를 해제하는 방법을 보여줍니다. 따라서 Java의 메모리 관리는 실제로 객체 할당 및 해제를 포함한 객체 관리입니다.
프로그래머의 경우 new 키워드를 사용하여 개체를 할당합니다. 개체에 대한 모든 참조를 null로 할당하면 프로그램이 더 이상 개체에 액세스할 수 없습니다. "접근할 수 없는" 모든 객체의 메모리 공간을 회수하는 일을 담당합니다.
GC의 경우 프로그래머가 객체를 생성하면 GC는 객체의 주소, 크기 및 사용량을 모니터링하기 시작합니다. 일반적으로 GC는 방향성 그래프를 사용하여 힙의 모든 개체를 기록하고 관리합니다. 이런 방식으로 어떤 개체가 "접근 가능"하고 어떤 개체가 "접근 불가능"한지 결정됩니다. GC가 일부 개체가 "접근 불가능"하다고 판단하면 GC는 이러한 메모리 공간을 회수해야 합니다. 그러나 GC가 다양한 플랫폼에서 구현될 수 있도록 하기 위해 Java 사양은 많은 GC 동작을 엄격하게 규제하지 않습니다. 예를 들어, 어떤 종류의 재활용 알고리즘을 사용할지, 언제 재활용을 수행할지 등 중요한 문제에 대한 명확한 규정이 없습니다. 따라서 서로 다른 JVM 구현자는 종종 서로 다른 구현 알고리즘을 사용합니다. 이는 또한 Java 프로그래머의 개발에 많은 불확실성을 가져옵니다. 이 기사에서는 GC 작업과 관련된 몇 가지 문제를 연구하고 이러한 불확실성이 Java 프로그램에 미치는 부정적인 영향을 줄이기 위해 노력합니다.
4. GC 세대 구분
JVM 메모리 모델의 Heap은 두 개의 큰 블록으로 나누어져 하나는 Young Generation이고 다른 하나는 Old Generation
1) Young Generation에는 주로 새로운 물건을 보관하는 데 사용되는 Eden Space라는 공간이 있습니다. 또한 두 개의 Survivor Space(from, to)가 항상 동일한 크기로 사용됩니다. 재활용할 때마다 살아남는 쓰레기.
2) Old Generation에서는 주로 수명주기가 긴 메모리 개체를 애플리케이션에 저장합니다.
3) Young Generation 블록에서는 가비지 수집이 일반적으로 빠른 Copying 알고리즘을 사용합니다. 각 GC 동안 살아남은 객체는 먼저 Eden에서 SurvivorSpace로 복사됩니다. 생존자 공간이 가득 차면 나머지 라이브 객체는 OldGeneration으로 직접 복사됩니다. 따라서 각 GC 후에 Eden 메모리 블록이 지워집니다.
4) Old Generation 블록에서 가비지 수집은 일반적으로 mark-compact 알고리즘을 사용하므로 속도는 느리지만 메모리 요구 사항이 줄어듭니다.
5) 가비지 수집은 여러 레벨로 구분됩니다. 레벨 0은 OLD 세그먼트의 가비지 수집을 전체(Full) 가비지 수집으로, 레벨 1 이상은 Young에서만 가비지 수집을 수행합니다. . 일반적으로 메모리 오버플로는 OLD 세그먼트 또는 Perm 세그먼트가 가비지 수집된 후에도 새 Java 객체를 수용할 메모리 공간이 없을 때 발생합니다.
5. 증분 GC
증분 GC는 일반적으로 JVM에서 하나 또는 프로세스 그룹에 의해 구현되는 GC이며, 그 자체도 사용자 프로그램과 마찬가지로 힙 공간을 차지하고 CPU도 차지합니다.
GC 프로세스가 실행되는 동안 애플리케이션 실행이 중지됩니다. 따라서 GC를 장시간 실행하면 사용자는 Java 프로그램의 멈춤을 느낄 수 있지만, GC가 너무 짧게 실행되면 객체 재활용률이 너무 낮아질 수 있습니다. 재활용해야 하지만 재활용되지 않았는데도 여전히 많은 메모리를 차지합니다. 따라서 GC를 설계할 때 Pause Time과 Recovery Rate 사이에서 trade-off가 이루어져야 한다. 좋은 GC 구현을 통해 사용자는 필요한 설정을 정의할 수 있습니다. 예를 들어, 메모리가 제한된 일부 장치는 메모리 사용량에 매우 민감하며 GC가 메모리를 정확하게 회수할 수 있기를 바라고 프로그램 속도에는 신경 쓰지 않습니다. 다른 실시간 온라인 게임은 긴 프로그램 중단을 허용하지 않습니다.
증분 GC는 특정 재활용 알고리즘을 사용하여 긴 중단을 여러 개의 작은 중단으로 나눕니다. 이러한 방식으로 GC가 사용자 프로그램에 미치는 영향이 줄어듭니다. 증분 GC는 전반적인 성능 측면에서 일반 GC만큼 효율적이지는 않지만 프로그램의 최대 일시 중지 시간을 줄일 수 있습니다.
Sun JDK에서 제공하는 HotSpot JVM은 증분 GC를 지원합니다. HotSpot JVM의 기본 GC 모드는 증분 GC를 사용하지 않는 것입니다. 증분 GC를 시작하려면 Java 프로그램 실행 시 -Xincgc 매개변수를 추가해야 합니다.
HotSpot JVM 증분 GC는 Train GC 알고리즘을 사용하여 구현됩니다. 기본 아이디어는 힙의 모든 객체를 생성 및 사용에 따라 그룹화(계층화)하고 자주 사용되는 객체와 관련 객체를 그룹화하는 것입니다. , 그룹은 프로그램이 실행됨에 따라 지속적으로 조정됩니다. GC가 실행되면 항상 가장 오래된(최근에 거의 액세스하지 않은) 개체를 먼저 재활용합니다. 전체 그룹이 재활용 가능한 경우 GC는 전체 그룹을 재활용합니다. 이러한 방식으로 각 GC 실행은 프로그램의 원활한 실행을 보장하기 위해 도달할 수 없는 개체의 특정 비율만 복구합니다.
Java의 GC 가비지 컬렉터의 기본 개념에 대한 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!