>  기사  >  类库下载  >  자바 메모리와 GC

자바 메모리와 GC

高洛峰
高洛峰원래의
2016-10-20 10:45:571483검색

Java 메모리 영역 및 메모리 오버플로

Java Virtual Machine의 메모리 할당 다이어그램:

자바 메모리와 GC

각 영역의 특성은 다음 표에 요약되어 있습니다.

자바 메모리와 GC

추가 설명:

멀티 스레드 상황에서는 여러 스레드가 힙에 메모리를 할당해야 할 수 있으며, 그러면 메모리 할당 동기화 문제가 발생할 수 있습니다. 해결책은 다음과 같습니다. 두 번째는 메모리 할당 작업을 동기화하는 것이고, 다른 하나는 TLAB를 사용하는 것입니다. 즉, Java 힙의 각 스레드에 대해 작은 스레드 전용 로컬 스레드 할당 버퍼를 미리 할당하는 것입니다. 이러한 방식으로 스레드가 메모리를 할당해야 할 때 자체 TLAB에서 이를 수행하여 동기화 오버헤드를 방지합니다. 그러나 TLAB가 완전히 할당되고 재할당되는 경우에는 여전히 동기화가 필요합니다.

클래스가 쓸모 없는 클래스인지 확인하려면 "재활용 가능" 조건은 다음과 같습니다. 1. 클래스의 모든 인스턴스가 재활용되었습니다. ; 2. 로드 이 클래스의 ClassLoader가 재활용되었습니다. 3 이 클래스의 java.lang.Class 객체는 어디에서도 참조되지 않습니다. 재활용이 불가능할 뿐이라는 점에 유의하세요.

메모리 할당 방법: 가상 머신에서 사용하는 방법은 메모리의 정규 여부에 따라 결정되며, 메모리의 규칙적인 여부는 재활용 알고리즘에 따라 결정됩니다.

포인터 충돌: 할당된 모든 메모리가 한쪽에 배치되고 여유 메모리가 다른 쪽에 배치된다고 가정합니다. 메모리를 할당해야 할 때 포인터가 사용됩니다. 포인터만 이동하면 됩니다. 이 방법을 포인터 충돌이라고 합니다. 이 방법은 Serial, ParNew 등의 Compact recycler에서 사용됩니다.

Free 목록: 가상 머신에 할당된 메모리와 사용 가능한 메모리가 규칙적이지 않고 서로 얽혀 있으므로 A 목록을 유지해야 합니다. 사용 가능한 메모리를 나타내는 데 사용됩니다. 메모리를 할당해야 할 경우 사용 가능한 메모리 크기를 찾기 위해 목록을 쿼리해야 합니다. 이 접근 방식을 사용 가능한 목록이라고 합니다. 이 방법은 Mark-Sweep 알고리즘을 기반으로 하는 기타 재활용 프로그램에서 사용됩니다. HotSpot 가상 머신의

개체의 메모리 레이아웃은 다음 표와 같습니다.

자바 메모리와 GC

Java 사양에서 참조 유형은 객체에 대한 참조만 규정할 뿐, 참조된 데이터에 액세스하는 방법은 지정하지 않습니다. 따라서 다양한 가상 머신에 대한 다양한 액세스 방법이 있습니다.

핸들 사용: 핸들에 대한 포인터를 포함하는 핸들 풀로 Java 힙의 영역을 따로 설정합니다. 객체 인스턴스 데이터 객체 데이터 유형의 포인터뿐 아니라 객체 핸들의 주소도 참조에 저장됩니다. 참조는 핸들을 통해 객체에 간접적으로 액세스합니다. 장점은 객체가 이동할 때 직사각형의 포인터만 변경하면 되며 해당 참조는 변경할 필요가 없다는 것입니다.

직접 액세스: 참조는 객체 주소를 저장하며 다음을 수행할 수 있습니다. 참조 액세스 데이터를 통해 직접 액세스합니다. Java 쌍의 데이터 객체에는 위에서 언급한 유형 포인터와 같은 객체의 데이터 유형에 대한 포인터가 포함되어 있습니다. 이 방법의 장점은 접근 속도가 빠르며, 핸들을 사용하는 방법에 비해 포인터 위치 지정에 따른 오버헤드가 절약된다는 점입니다. HotSpotVM은 이 방법을 사용합니다.

두 가지 사용 방법의 그림은 다음과 같습니다. 이미지 출처 http://www.th7.cn/Program/java/201604/846729.shtml

자바 메모리와 GC

가비지 수집 알고리즘

객체가 죽었고 더 이상 사용할 수 없는지 여부를 결정하는 두 가지 알고리즘이 있습니다.

참조 카운팅 알고리즘: 객체의 경우 해당 객체가 사용된 횟수 참조된 값은 1씩 증가하고, 개수는 1씩 증가하며, 참조가 유효하지 않게 되면 1씩 감소합니다. 개수가 0에 도달하면 개체가 죽은 것으로 간주됩니다. 이 알고리즘은 효율성이 높다는 특징이 있지만 객체 간 상호 참조 문제를 해결하기가 어렵습니다. 이 알고리즘은 MS의 COM 기술과 Python 등에서 사용됩니다.

도달성 분석 알고리즘: 이 알고리즘의 핵심은 GC Roots에서 시작하여 참조되는 모든 개체를 검색하는 것입니다. 개체와 GC 루트 사이에 참조 체인이 없으면 개체는 죽은 것으로 간주됩니다. 이 알고리즘을 사용하기 위해 Java, C# 등이 사용됩니다.

GC 루트로 사용할 수 있는 개체는 다음과 같습니다.

가상 머신 스택(스택 프레임의 로컬 변수 테이블)에서 참조되는 개체

클래스 정적 속성에서 참조되는 개체 메소드 영역 객체

메소드 영역에서 상수로 참조되는 객체

네이티브 메소드

에서 참조되는 객체는 Java에서 네 가지 참조 강점을 갖습니다.

강한 참조: 강력한 참조는 가비지 수집기에 의해 결코 재활용되지 않습니다.

소프트 참조: 시스템은 여전히 ​​존재하지만 필요하지 않은 객체를 나타내기 위해 SoftReference 클래스를 제공합니다. 재활용 시점은 참조 객체를 재활용한 후 메모리가 부족할 경우 해당 참조를 재활용하는 것입니다.

약한 참조: WeakReference 클래스로 표현되는 이 유형의 참조는 다음 가비지 수집까지만 유지됩니다. 가비지 수집기가 작동하면 현재 메모리가 충분한지 여부에 관계없이 약한 참조와 관련된 개체만 재활용됩니다. 즉, GC가 발생하는 한 약한 참조는 재활용되어야 합니다. 더 이상 GC 루트에 도달하지 않는 참조 체인과의 차이점은 이러한 개체는 약한 참조를 통해 계속 액세스할 수 있지만 참조 체인이 없는 개체에는 다시 액세스할 수 없다는 것입니다.

가상 참조: PhantomReference를 통해 구현되며, 객체의 수명에 영향을 주지 않습니다. 가상 참조가 참조하는 객체가 재활용될 때 시스템 알림을 받는 것이 그 존재의 의미입니다.

시스템의 GC 워크플로우는 아래 그림과 같습니다. 일반적으로 재활용되는 개체는 마킹 프로세스를 두 번 거치며 재활용을 피하기 위해 finalize 메서드에서 자체적으로 저장될 수 있습니다.

자바 메모리와 GC

몇 가지 일반적인 가비지 수집 알고리즘:

자바 메모리와 GC

HotSpot VM의 가비지 수집 알고리즘에 대한 구체적인 구현 세부 사항: 정확한 결과적으로 GC는 스캔 중에 모든 스레드를 정지해야 합니다. 현재 주류 Java 가상화는 정확한 GC를 채택합니다. 즉, 시스템은 각 메모리 위치의 데이터가 어떤 데이터 유형인지 알고 있습니다. 예를 들어 OopMap이라는 데이터 구조를 사용하여 이러한 매핑 레코드를 구현합니다. 이러한 정보를 통해 가상 머신은 개체 참조가 저장된 위치를 직접 알 수 있으므로 메모리를 하나씩 확인할 필요가 없고 GC 스캔 속도가 빨라집니다. 프로그램의 각 명령어는 참조 관계나 메모리 데이터의 변화로 이어질 수 있으며, 이는 OopMap의 변화로 이어질 수 있습니다. 이 경우 각 명령어마다 해당 OopMap 데이터가 생성되면 꽤 많은 공간을 차지하게 되므로, 안전점(SafePoint)은 각 스레드가 해당 스레드에 해당하는 안전점으로 실행될 때만 GC 스캔을 수행하므로 안전점의 명령어에 대해 OopMap만 생성할 수 있으므로 개수가 줄어듭니다. OopMap의. 안전한 지점의 선택은 GC 빈도와 시스템 성능의 포괄적인 영향을 고려해야 합니다. 일반적으로 메서드 호출, 루프 점프, 예외 점프 등 "프로그램을 오랫동안 실행하게 하는 특성을 갖는" 지점이 있습니다. 선택된. 스레드가 안전한 지점까지 실행되고 GC 스캔을 위해 중지되도록 하기 위해 선제적 중단과 사전적 중단의 두 가지 방법이 있습니다. 여기서 또 다른 문제가 있는데, Sleep 상태에 있는 Thread를 만나면 움직이지 않습니다. 안전한 지역(SafeRegion)도 제안되었습니다. 즉, 이 영역의 지점이 안전 지점입니다. 스레드가 안전 지점에 진입한 후 안전 영역에 진입했음을 표시하고 안전 영역을 떠나기 전에 GC가 완료될 때까지 기다려야 합니다.

각 가비지 수집기:

자바 메모리와 GC

가장 일반적인 메모리 할당 규칙:

객체 우선순위 할당 Eden 영역: Eden 영역의 메모리가 충분하지 않으면 시스템은 더 빠른 Minor GC

를 시작합니다. 대형 객체는 Old Generation에 직접 입력됩니다. 긴 배열 및 문자열과 같은 대형 객체의 경우 Old Generation 영역에 할당되어 직접 이동됩니다. 따라서 수명주기가 짧은 대형 개체는 GC를 일으킬 가능성이 높으므로 최대한 피해야 합니다.

장기 생존 객체는 Old Generation으로 들어갑니다. 객체가 Survivor 영역에서 기본적으로 15번의 Minor GC에서 살아남으면 Old Generation으로 이동합니다.

동적 개체 연령 결정: 이 문서는 이전 항목과 결합됩니다. 생존자에서 동일한 연령의 모든 개체 크기의 합이 생존자의 절반을 초과하는 경우 나이가 이상인 개체는 다음과 같습니다. 이 연령과 동일하면 15번을 기다릴 필요가 없습니다.

공간 할당 보장: 새로운 세대를 위한 복사 수집 알고리즘. 매개 변수가 허용되면 Minor GC를 실행한 후 살아남은 모든 객체를 Survivor에 배치할 수 없으면 많은 객체가 Old Generation 영역에 직접 배치됩니다. Old Generation에 공간이 충분하지 않으면 더 많은 공간을 확보하기 위해 Full GC가 발생합니다


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