> Java > java지도 시간 > Java 가비지 수집 메커니즘이란 무엇입니까?

Java 가비지 수집 메커니즘이란 무엇입니까?

零下一度
풀어 주다: 2017-06-25 11:04:18
원래의
1348명이 탐색했습니다.

1. 문제

저자는 최근 Java의 가비지 수집 메커니즘에 대해 많은 문제에 직면했기 때문에 Java의 가비지 수집이 무엇인지 공유하기 위해 특별히 블로그를 작성했습니다. 소위 가비지 수집은 jvm이 개체가 존재할 필요가 없다고 생각하여 정리하더라도 문제가 발생한다는 것을 의미합니다.

  1. 물건을 재활용해야 하는지 어떻게 판단하나요?

  2. 일반적인 가비지 수집 알고리즘은 객체를 어떻게 재활용하나요?

  3. 전형적인 가비지 컬렉터는 무엇인가요?

문제를 하나씩 살펴보겠습니다

2. 물건을 재활용해야 하는지 판단하는 방법

여기서 우리는 먼저 질문을 이해합니다: 물건이 "쓰레기"로 결정되면 어떻게 될까요? 가비지 수집기의 임무는 새 객체가 사용할 수 있도록 가비지 객체가 차지하는 공간을 회수하는 것이므로 가비지 수집기는 객체가 "쓰레기"인지 어떻게 판단합니까? —즉, 물건의 재활용 가능 여부를 판단하는 방법입니다. 일부 개체는 JVM 메모리가 부족하여 정리해야 합니다. 다음 라운드에서 재활용해야 하는 개체는 정리됩니다.

  Java에서는 객체가 참조를 통해 연결됩니다. 즉, 객체를 조작하려면 참조를 통해 수행해야 합니다. 따라서 간단한 방법은 참조 카운팅을 사용하여 객체를 재활용할 수 있는지 여부를 결정하는 것입니다. 일반성을 잃지 않고 객체에 연관된 참조가 없으면 해당 객체는 기본적으로 다른 곳에서 사용될 가능성이 없으며 재활용 가능한 객체가 됩니다. 이 방법을 참조 카운팅이라고 합니다.

 이 방법은 간단하고 투박하며 매우 효율적입니다. 효율성이 높으면 필연적으로 몇 가지 문제가 발생합니다. 일부 개체에 순환 참조가 있는 경우 해당 개체를 null에 할당하더라도 이 알고리즘은 여전히 ​​재활용될 수 없습니다. 아래 코드를 보세요

public class GcTest {public Object object = null;    public static void main(String[] args) {
        
        GcTest gcTest1 = new GcTest();
        GcTest gcTest2 = new GcTest();
        
        gcTest1.object = gcTest1;
        gcTest2.object = gcTest2;
        
        gcTest1 = null;
        gcTest2 = null;
    }
}
로그인 후 복사

gcTest1과 gcTest2가 null임에도 불구하고 그들이 가리키는 객체는 더 이상 접근할 수 없게 되지만, 서로를 참조하기 때문에 참조 횟수가 0이 아니므로 가비지 컬렉션 서버는 결코 재활용하지 않을 것입니다.

 위의 문제가 노출되었습니다. jvm이 이 문제를 어떻게 해결하는지 살펴보겠습니다. 이러한 문제를 해결하기 위해 Java에서는 도달성 분석 방법을 채택하고 있습니다. 이 방법의 기본 아이디어는 일련의 "GC Roots" 개체를 시작점으로 검색하는 것입니다. "GC Roots"와 개체 사이에 도달 가능한 경로가 없으면 해당 개체는 도달할 수 없다고 합니다. 도달할 수 없는 것으로 결정된 객체가 반드시 재활용 가능한 객체가 되는 것은 아니라는 점에 유의해야 합니다. 도달 불가능하다고 판단된 객체가 재활용 가능 객체가 되기 위해서는 최소한 두 번의 마킹 과정을 거쳐야 합니다. 이 두 번의 마킹 과정에서도 여전히 탈출하여 재활용 가능 객체가 될 가능성이 없다면 기본적으로 재활용 가능 객체가 됩니다. . "JVM 심층 이해"에서는 저자가 GC Roots의 개념을 간략하게 소개합니다. 이에 대해 더 알고 싶다면 저자가 소개한 책을 읽어보세요.

 객체를 재활용할 수 있는지 여부를 결정하기 위해 다음 세 가지 유형의 객체가 jvm에서 GC 루트로 사용됩니다. (일반적으로 가상 머신 스택과 정적 참조만 알면 됩니다.)

 1. (정확하게 말하면 가상 머신 스택의 스택 프레임(프레임))에서 참조되는 개체입니다. 우리는 각 메소드가 실행될 때 jvm이 해당 스택 프레임을 생성한다는 것을 알고 있습니다(스택 프레임에는 피연산자 스택, 지역 변수 테이블 및 런타임 상수 풀에 대한 참조가 포함되어 있음). 객체의 참조(물론 기타 기본 유형 데이터) 메서드가 실행되면 스택 프레임이 가상 머신 스택에서 제거됩니다. 이러한 방식으로 임시로 생성된 객체의 참조는 더 이상 존재하지 않습니다. 이러한 임시 개체를 가리키는 모든 gc 루트는 없으며 이러한 개체는 다음 GC 중에 재활용됩니다. 2. 메서드 영역의 클래스 정적 속성에 의해 참조되는 개체입니다. 정적 속성은 이 유형(클래스)의 속성이며 어떤 인스턴스에도 속하지 않으므로 이 속성은 자연스럽게 gc 루트 역할을 합니다. 이 클래스가 존재하는 한 이 참조가 가리키는 객체도 존재합니다. 클래스도 재활용될 예정인데 나중에 설명하겠습니다

 

3. 네이티브 스택이 참조하는 객체

 다음은 소프트 참조(softReference)와 약한 참조(weakReference)의 객체 가비지 수집에 대한 소개입니다. 그랬어요

String str = new String("hello");//A
SoftReference<String> sr = new SoftReference<String>(new String("java"));//B
WeakReference<String> wr = new WeakReference<String>(new String("world"));//C
로그인 후 복사

위 객체들 중 재활용 상황은 다음과 같습니다. B는 메모리가 부족할 때 String 객체를 재활용 가능한 객체로 판단하고, C는 어떤 상황에서도 String 객체를 재활용 가능한 객체로 판단합니다. 즉, 소프트 참조는 메모리 오버플로(OOM)가 발생하면 재활용되는 반면 약한 참조는 무슨 일이 있어도 다음 재활용 라운드에서 재활용됩니다.

  일반적으로 JVM은 이러한 객체를 재활용합니다.

  1. 명시적으로 null에 대한 참조를 할당하거나 이미 객체를 가리키는 참조를 새 객체로 가리킵니다.

 2. 로컬 참조가 가리키는 객체입니다.

 3. 위에서 언급한 약한 참조입니다.

3. 가비지 수집 알고리즘

어떤 쓰레기를 재활용할 수 있는지 결정한 후 가비지 수집기가 해야 할 일은 가비지 수집을 시작하는 것인데, 가비지 수집을 효율적으로 수행하는 방법에 대한 문제가 있습니다. Java 가상 머신 사양에서는 가비지 컬렉터 구현 방법을 명확하게 규정하지 않으므로 다양한 제조업체의 가상 머신에서 가장 일반적으로 사용되는 HotShot을 예로 들어 핵심만 설명합니다. 몇 가지 일반적인 가비지 수집 알고리즘에 대한 아이디어.

1. Mark-Sweep(마크-클리어) 알고리즘

  가장 기본적인 가비지 컬렉션 알고리즘인 이유는 구현하기가 가장 쉽고 아이디어도 가장 단순하기 때문입니다. 마크 스윕 알고리즘은 마크 단계와 클리어 단계의 두 단계로 나뉩니다. 마킹 단계의 임무는 재활용이 필요한 모든 객체를 표시하는 것이고, 클리어 단계는 표시된 객체가 차지한 공간을 복구하는 것입니다. 이 다이어그램은 인터넷에서 가져온 것이며 마크 클리어 알고리즘 처리 전후의 메모리 분포를 보여줍니다.

아래 사진은 모두 시뮬레이션된 메모리 블록입니다. 빨간색은 사용되지 않은 메모리 블록, 회색은 재활용할 개체의 메모리 블록, 노란색은 라이브 개체입니다.

재활용 후

이러한 작업에는 단점이 있음을 쉽게 알 수 있습니다. 표시된 개체가 지워진 후에는 메모리 블록이 흩어집니다. 많은 양의 메모리를 차지하는 개체가 있으면 이때 다시 쓰레기를 실행해야 합니다. 이 큰 물체를 위한 공간을 확보하기 위해.

2. 복사 알고리즘

 Mark-Sweep 알고리즘의 단점을 해결하기 위해 복사 알고리즘이 제안되었습니다. 사용 가능한 메모리를 용량에 따라 두 개의 동일한 크기 블록으로 나누고 한 번에 그 중 하나만 사용합니다. 이 메모리 블록이 부족해지면 살아남은 개체를 다른 블록에 복사한 다음 사용한 메모리 공간을 한꺼번에 정리하여 메모리 조각화 문제가 발생할 가능성을 줄입니다.

재활용 전

재활용 후

복사 알고리즘은 일반 메모리를 미리 비우고 가비지 수집 중에 살아남은 객체를 메모리의 나머지 절반으로 이동합니다. 하지만 이 메모리 이동은 너무 많은 것을 소비합니다. 메모리가 단편화되지는 않았지만 가격이 너무 높습니다.

3. Mark-Compact(Mark-Compact) 알고리즘

 Copying 알고리즘의 단점을 해결하고 메모리 공간을 최대한 활용하기 위해 Mark-Compact 알고리즘이 제안되었습니다. 이 알고리즘의 마킹 단계는 Mark-Sweep과 동일하지만 마킹 완료 후 재활용 가능한 객체를 직접 정리하지 않고, 살아남은 객체를 한쪽 끝으로 이동한 다음 끝 경계 외부의 메모리를 정리합니다. 구체적인 프로세스는 아래 그림과 같습니다.

재활용 전

재활용 후

4. 세대별 수집(세대별 수집) 알고리즘

세대별 수집 알고리즘은 현재 대부분의 JVM 가비지 수집기 알고리즘에서 사용됩니다. . 핵심 아이디어는 객체의 수명 주기에 따라 메모리를 여러 영역으로 나누는 것입니다. 일반적인 상황에서 힙 영역은 Tenured Generation과 Young Generation으로 구분됩니다. Old Generation의 특징은 각 가비지 수집 중에 소수의 객체만 재활용하면 되고 모든 객체를 재활용할 필요는 없다는 것입니다. Young Generation의 특징은 각 가비지 수집 과정에서 재활용해야 할 객체가 많기 때문에 다양한 세대의 특성에 따라 가장 적합한 수집 알고리즘을 채택할 수 있다는 것입니다. System.gc() 메서드를 호출하여 재활용 상황을 확인할 수 있습니다.

현재 대부분의 가비지 수집기는 새 세대의 복사 알고리즘을 채택합니다. 왜냐하면 대부분의 객체는 새 세대의 각 가비지 수집에서 재활용되어야 하기 때문입니다. 즉, 복사 작업 수가 적지만 실제로는 1이 아닙니다. 1. 신세대의 공간은 비율에 따라 나누어진다. 일반적으로 신세대는 재활용 시 에덴 공간과 하나의 생존자 공간을 사용할 때마다 더 큰 에덴 공간과 2개의 작은 서바이버 공간으로 나누어진다. , Eden 및 Survivor에서 살아남은 개체를 다른 Survivor 공간에 복사한 다음 방금 사용한 Eden 및 Survivor 공간을 정리합니다.

구세대의 특성은 매번 적은 수의 객체만 재활용된다는 것이므로 일반적으로 Mark-Compact 알고리즘이 사용됩니다.

힙 영역 외부에는 클래스, 상수, 메서드 설명 등을 저장하는 데 사용되는 영구 세대(Permanet Generation)인 또 다른 세대가 있습니다. 영구 생성의 재활용은 주로 버려진 상수와 쓸모 없는 클래스라는 두 부분을 재활용합니다.

3. 전형적인 가비지 컬렉터

다음은 몇 가지 확률적인 내용입니다. 작성자가 이해한 것 같아서 공유하려고 여기에 옮겼습니다.

1. Serial/Serial Old collection 가장 기본적이고 가장 오래된 수집기이며 단일 스레드 수집기이며 가비지 수집을 수행하는 동안 모든 사용자 스레드를 일시 중지해야 합니다. Serial Collector는 신세대를 위한 Collector로 Copying 알고리즘을 사용하며, Serial Old Collector는 Old Generation을 위한 Collector로 Mark-Compact 알고리즘을 사용한다. 구현이 간단하고 효율적이라는 장점이 있지만, 사용자에게 일시 중지를 유발한다는 단점이 있습니다.

2.ParNew

 ParNew 수집기는 가비지 수집을 위해 다중 스레드를 사용하는 직렬 수집기의 다중 스레드 버전입니다.

3.Parallel Scavenge

Parallel Scavenge 컬렉터는 차세대 다중 스레드 컬렉터(병렬 컬렉터)로, 재활용 중에 다른 사용자 스레드를 일시 중지할 필요가 없습니다. 이 컬렉터는 이전 컬렉터와 다릅니다. 두 수집기는 서로 다르며 주로 제어 가능한 처리량을 달성하는 것입니다.

4.Parallel Old

Parallel Old는 멀티스레딩과 Mark-Compact 알고리즘을 사용하는 Parallel Scavenge Collector(병렬 컬렉터)의 구세대 버전입니다.

5.CMS

 CMS(Current Mark Sweep) 콜렉터는 가장 짧은 재활용 휴지 시간을 얻는 것을 목표로 하는 콜렉터이며 Mark-Sweep 알고리즘을 사용하는 동시 콜렉터입니다.

6.G1

G1 컬렉터는 오늘날 컬렉터 기술의 가장 최첨단 개발품이며 서버 측 애플리케이션을 위한 컬렉터이며 멀티 CPU 및 멀티 코어 환경을 최대한 활용할 수 있습니다. 따라서 이는 병렬 및 동시 수집기이며 예측 가능한 일시 중지 시간을 모델링합니다.

IV.요약 및 보충

  객체의 메모리 할당은 일반적으로 힙에 할당됩니다. 객체는 주로 신세대의 Eden Space와 From Space에 할당되는 경우도 있습니다. . 새로운 세대의 Eden Space와 From Space의 공간이 부족하면 GC가 시작됩니다. GC 이후 Eden Space와 From Space가 객체를 수용할 수 있으면 Eden Space와 From Space에 배치됩니다. GC 과정에서 Eden Space와 From Space에 남아있는 객체들은 To Space로 이동되고, 이후 Eden Space와 From Space는 정리됩니다. 정리 프로세스 중에 개체를 저장할 공간이 충분하지 않으면 개체는 이전 세대로 이동됩니다. GC가 수행된 후에는 Eden 공간과 To Space가 사용되며 다음 GC에서는 살아남은 객체가 From Space로 복사되며 이 주기가 반복됩니다. 객체가 Survivor 영역의 GC를 벗어나면 객체의 age가 1씩 증가합니다. 기본적으로 객체의 age가 15세가 되면 Old Generation으로 이동합니다.

일반적으로 대형 개체는 Old Generation에 직접 할당됩니다. 소위 대형 개체는 많은 양의 연속 저장 공간이 필요한 개체를 말합니다. 가장 일반적인 대형 개체는 다음과 같습니다.

byte[] data = new byte[4*1024*1024]

 이것은 일반적으로 Old Generation에서 직접 저장 공간을 할당합니다.

 물론 할당 규칙이 100% 고정된 것은 아니며 현재 사용되는 가비지 수집기 조합과 JVM의 관련 매개 변수에 따라 다릅니다.

위 내용은 Java 가비지 수집 메커니즘이란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿