>  기사  >  Java  >  java--가비지 수집 메커니즘에 대한 자세한 설명

java--가비지 수집 메커니즘에 대한 자세한 설명

巴扎黑
巴扎黑원래의
2017-07-18 18:15:431520검색

개요

1. 쓰레기

JVM 가비지 수집은 주로 힙에 있는 쓰레기를 대상으로 합니다. 스레드가 시작될 때 스택에 공간이 할당되고 스레드가 끝나면 자동으로 공간이 해제되기 때문입니다. 실시간이 필요하지 않습니다. 모니터링; 메서드 영역은 주로 전체 프로그램 실행 중에 유효한 클래스 정보, 정적 변수 및 상수를 저장하며 재활용해야 할 개체가 없습니다.

가비지(Garbage)는 스레드에서 접근할 수 없는 객체를 의미합니다. 객체는 스레드에 표시되어 있어야만 사용할 수 있으며, 참조가 없는 객체로도 간단히 이해할 수 있습니다. 엄밀히 말하면 객체에 대한 참조가 없는 표현은 가비지의 범위를 좁힙니다. 예를 들어 순환 참조에서 객체 A는 다른 객체 B를 참조하고 객체 B는 A를 참조합니다. A와 B 간의 참조 관계만 존재합니다. 둘 사이에는 A 또는 B를 참조하는 외부 개체가 없으므로 A와 B는 프로그램 실행에 포함될 수 없습니다. 즉, 어떤 스레드에서도 액세스할 수 없으며, 동기에 따라 쓸모 없는 개체가 됩니다. 쓰레기를 정의하면, 그들은 더 이상 쓰레기가 아닙니다. 사용된 객체는 쓰레기이며, A와 B는 당연히 쓰레기에 속합니다.

때로는 쓰레기를 쓸모없는 물건이라고도 하고 쓰레기가 아닌 물건을 살아있는 물건이라고 부르기도 합니다.

2. 메모리 누수

쓸데없는 객체가 계속 메모리를 점유하여 메모리 낭비를 일으키는 현상을 메모리 누수라고 합니다. 메모리 누수의 근본 원인은 다음 코드와 같이 수명이 긴 객체가 사용 후에도 수명이 짧은 객체에 대한 참조를 계속 유지하기 때문입니다.

    public void test02(){
        Object obj = new Object();
        obj.doSome();//调用了对象中的doSome方法以后,就不再使用该对象,但是依然持有对象的引用obj        ...................... 
    }

메서드에서 객체가 생성됩니다. 객체 생성의 목적은 객체의 doSome 메소드에 액세스하는 것입니다. 이 때 객체는 더 이상 참조 변수 obj에 액세스되지 않습니다. 개체에 참조가 있으므로 개체는 가비지로 간주되지 않지만 개체는 쓸모 없는 개체가 되므로 가비지 수집기가 개체가 차지한 메모리 공간을 회수할 수 있도록 역참조해야 합니다. obj=null;" 역참조.

3. 메모리 재활용

가비지 컬렉터는 객체를 재활용하는 것이 아니라 쓸모없는 객체가 차지한 메모리 공간을 다시 사용할 수 있도록 합니다.

4. 메모리 조각화

그림과 같이 메모리 할당 및 재활용 과정에서 생성되는 작고 불연속적인 여유 공간:

재활용을 기다리는 공간으로 인해 흩어집니다. 배열을 하면 재활용이 완료된 후 사용 가능한 공간이 사용된 공간에 따라 독립적인 작은 단위로 나누어집니다. 이러한 단위는 크기가 작기 때문에 큰 데이터를 위해 추가 공간을 열어야 하므로 메모리 낭비가 발생합니다. .

가비지 판별을 위한 두 가지 알고리즘

1. 참조 계산 알고리즘

객체가 생성되면 변수가 객체를 참조할 때마다 참조 카운터가 객체에 추가됩니다. 1이고 변수가 참조를 해제하면 카운터가 1씩 감소합니다. 언제든지 카운터가 0이면 해당 개체를 참조하는 개체가 없으며 개체가 가비지가 된다는 의미입니다.

참조 카운팅 알고리즘의 본질적인 결함은 순환 참조 문제를 해결할 수 없다는 것입니다. 즉, 순환에서 참조하는 두 객체가 더 이상 사용되지 않더라도 여전히 사용 가능한 객체로 간주되어 더 이상 사용되지 않습니다. 가비지 컬렉터에 의해 재활용됩니다. JVM 가비지 수집 메커니즘은 이 알고리즘을 사용하지 않고 다음과 같은 도달성 분석 알고리즘을 사용합니다.

2. 도달성 분석 알고리즘

추적을 사용하여 추적을 통해 도달할 수 있는 객체는 모두 살아있는 객체이고, 추적 가능하거나 도달할 수 없는 객체는 살아있는 객체입니다. 쓸모없는 물건이다. 추적의 시작점은 현재 액세스 중인 모든 개체입니다. 이 개체에서 시작하여 해당 개체가 참조하는 개체를 찾고, 참조 체인에 없는 개체는 순서대로 반복됩니다. 스레드에 의해 사용되며 쓰레기입니다. 아래 그림과 같이 왼쪽에 참조 체인이 형성되어 있으며, 오른쪽에 있는 개체는 모두 살아있는 개체이지만 스레드의 참조 체인 외부에 있습니다. , 그래서 쓸모없는 객체입니다.

이런 종류의 분석은 정적이 아닌 동적이며 개체 참조 관계가 변경됨에 따라 변경됩니다.

세 가지 객체 저장 구분

객체마다 수명 주기가 다릅니다. 적시에 메모리를 재활용하기 위해 수명 주기가 짧은 객체에 대해 가비지 수집 작업이 자주 수행되는 반면, 수명 주기가 긴 객체는 상대적으로 가비지(Garbage) 수집 스캔 횟수가 적으므로 오버헤드를 절약하고 가비지 수집 횟수를 줄이기 위해 서로 다른 수명 주기를 가진 객체를 서로 다른 메모리 영역에 저장하므로 서로 다른 가비지 수집 전략이 사용됩니다. 채택될 수 있습니다.

JVM은 객체 저장 공간을 신세대, 구세대, 영구세대의 세 영역으로 구분합니다.

1. 신세대

신세대는 짧은 수명 주기로 객체를 신속하게 재활용하기 위해 설립되었습니다. 신세대는 에덴, 생존자, 생존자 세 부분으로 나누어지며 공간 비율은 8:1:1입니다.

새로 생성된 개체는 먼저 eden에 배치되고 여러 GC(가비지 수집)가 수행된 후 살아남은 개체는 from Survivor 영역으로 전송됩니다. 가 가득 차면 살아남은 객체는 생존자에게 전달됩니다. 생존자 영역이 가득 차면 살아남은 객체는 이전 세대로 승격됩니다.

JVM은 젊은 세대의 개체에 대해 자주 GC를 수행합니다. 대부분의 개체는 젊은 세대에서 재활용되고 소수는 Old 세대로 들어갑니다.

2. Old Generation

Old Generation의 개체는 여러 GCS에서 살아남은 개체이며 수명 주기가 비교적 길고 상대적으로 안정적이므로 GC 작업 횟수가 줄어듭니다.

3. 영구 생성

영구 생성은 클래스 정보, 정적 변수 및 상수를 저장하는 영역이기도 하며, 일반적으로 가비지 수집기 처리가 필요하지 않습니다.

네 가지 가비지 수집 알고리즘

가비지 수집 알고리즘은 가비지 확인 후 실제 수집에 사용되는 알고리즘입니다. 3가지 일반적인 알고리즘이 있습니다.

1. 표시 지우기 방법

먼저 쓸모없다고 표시합니다. 객체를 사용한 후 객체가 차지하는 메모리 공간을 재활용하면 메모리 조각화가 발생하므로 이 알고리즘은 기본적으로 사용되지 않습니다.

2. 복사 알고리즘

은 메모리 공간을 여러 영역으로 나눕니다. 가비지 수집 중에 한 영역에 남아 있는 모든 개체가 다른 영역으로 복사된 다음 해당 영역이 지워져 메모리 조각화가 발생하지 않습니다. . 이 알고리즘은 eden 영역에서 fromsurvivor 영역으로 복사한 다음 tosurvivor 영역으로 복사하는 차세대 가비지 수집 중에 사용됩니다. 살아남는 객체가 적기 때문에 복사하는 동안 공간을 덜 차지합니다.

3. 표시 정리 알고리즘

먼저 지워야 할 개체를 표시하고, 살아남은 개체를 모두 한쪽 끝으로 옮긴 다음 쓸모 없는 개체를 모두 지웁니다. 신세대와 달리 구세대는 각 GC 이후에 더 많은 개체가 남아 있으며 복사 알고리즘은 많은 메모리를 차지합니다. "mark-organize" 알고리즘은 메모리 조각화를 일으키지 않고 메모리를 절약합니다.

5 가비지 수집 타이밍

세대마다 GC 메커니즘이 다릅니다: Scavenge GC 및 Full GC.

신세대 eden 영역이 가득 차고 새로 생성된 객체가 공간 적용에 실패하면 Scavenge GC가 트리거되어 eden 영역에 대해 GC 조작을 수행하고 쓸모 없는 객체를 정리하고 공간을 만듭니다. Scavenge GC는 새로운 세대에서만 작동합니다.

Old Generation이 꽉 차거나 Persistency Generation이 꽉 차거나 System.gc() 메서드가 명시적으로 호출되면 Full GC가 트리거되어 모든 객체 저장 영역에서 GC를 수행하게 됩니다. Full GC 빈도는 낮아야 합니다.

여섯 가지 다른 방법

1. System.gc()

가비지 수집기는 데몬 스레드를 사용하므로 특정 시간에 시작되지 않을 수 있습니다. 통제될 수 있다. 또한 는 리소스를 많이 소모하므로 일반적인 상황에서는 명시적으로 호출하지 마세요.

2.finalize()

객체 범위 방법. JVM이 객체에 액세스할 수 없음을 확인한 후 호출되며, 한 번만 호출할 수 있으며 일반적으로 연결 리소스를 해제하는 데 사용됩니다. 이 메소드가 호출된 후 가비지 컬렉터는 객체가 차지하는 공간을 즉시 회수하지 않습니다. 왜냐하면 이 메소드가 실행되는 동안 객체에 다시 액세스할 수 있기 때문입니다. 대신 객체가 점유한 공간을 확인한 후에만 회수합니다. 다음 gc 공간에서는 여전히 객체에 액세스할 수 없습니다.

GC 오버헤드를 줄이기 위한 7가지 조치

  1. 정적 변수의 사용을 피하세요. 정적 변수의 수명 주기는 애플리케이션의 수명 주기와 동일하기 때문입니다. 메모리 공간을 차지합니다.

  2. OutputStreamInputStreamConnectionSocket과 같은 리소스 연결은 사용 후 즉시 닫아야 하며 리소스는 적시에 해제되어야 합니다.

  3. System.gc()를 명시적으로 호출하지 마세요. 이 방법은 비용이 많이 드는 Full GC를 실행할 수 있기 때문입니다.

  4. 메서드가 실행된 후 임시 변수는 쓰레기가 되므로 임시 변수의 사용을 줄이세요. 임시 변수가 많으면 GC 수가 늘어나고 시스템 소비도 늘어납니다.

  5. 객체 참조가 완료된 후 시간에 맞춰 참조를 해제하여 시간에 맞춰 메모리 공간을 회수합니다.

  6. 변경 가능한 개체를 최대한 사용하고 변경 불가능한 개체의 사용 횟수를 줄이세요.

  7. 기본 유형 변수는 해당 래퍼 클래스보다 훨씬 적은 리소스를 차지하므로 해당 래퍼 클래스 대신 기본 유형 변수를 사용해 보세요.

  8. 객체를 분산적으로 생성하고 삭제하려면 객체를 함께 생성하려면 많은 공간이 필요하고 이로 인해 Full GC가 발생하여 시스템 소비가 즉시 증가할 가능성이 높기 때문입니다. 객체를 집중적으로 삭제하면 쓸모없는 객체가 순식간에 대량으로 나타날 수 있으며, 이로 인해 Full GC가 발생할 수도 있습니다.

참조:


     
     
     
     
     

위 내용은 java--가비지 수집 메커니즘에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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