JVM 가비지 수집 메커니즘은 Java 프로그래머가 알아야 할 지식으로 프로그램 튜닝에 큰 도움이 됩니다 (대형 공장 면접의 필수 문제이기도 함).
가비지 수집 메커니즘을 이해하려면 주로
(1) 가비지 수집이 지향하는 대상은 누구입니까?
(2) 가비지 수집 알고리즘은 무엇입니까?
(3) 가비지 수집기에는 어떤 것이 있습니까? 각 수집기의 특징은 무엇입니까?
다음에 자세히 설명하겠습니다.
1, 가비지 수집 대상 대상
은 문자 그대로 가비지 수집입니다. 중요한 것은 쓰레기입니다. 어떤 대상이 쓰레기입니까? 간단히 말해서 이렇게 해서 또 어떤 대상이 죽었는지, 대상이 이미 죽었는지 어떻게 판단할 수 있습니까?
객체가 죽었는지 여부를 결정하는 두 가지 알고리즘과 객체 참조 분류가 있습니다.
(1) 참조 개수 알고리즘:
도 문자 그대로 객체에 참조 카운터를 추가하여 참조 +1 을 추가합니다 참조가 0 이면 객체는 쓸모없는 것으로 판단할 수 있습니다.
이점: 간단하고 효율적입니다.
단점: 순환 참조 (a 가 b 를 참조하고 b 도 a 를 참조하는 경우) 문제를 해결할 수 없습니다.
(2) 루트 검색 알고리즘 (즉, GC Roots):
는 GC Roots 라는 일련의 객체를 통해 아래로 검색합니다. 경로는 참조 체인입니다. 객체가 GC Roots 를 위로 검색할 수 없을 때
객체가 GC Roots 에 도달할 수 없는 경우 재확보를 위해 두 번 태그를 거쳐야 하며, 처음 태그를 지정할 때 finalize 메소드를 실행해야 하는지 여부를 결정합니다 (실행할 필요가 없는 경우: finalize 메소드가 구현되지 않았거나 이미 실행된 경우). Finalize 메소드를 실행해야 하는 경우 재활용 대기열에 배치되고, finalize 메소드를 실행한 후 객체를 GC Roots 와 다시 연결할 수 없는 경우 재활용됩니다.
매우 추상적이죠, 그렇죠? 명확한 설명을 해주시겠습니까?
예를 들어 휴대폰이 고장나면 (도달 불가 대상), 돈이 있으면 그냥 수거 (즉, finalize 방법이 구현되지 않은 경우) 하고, 수리가 잘 되지 않으면 (finalize 방법이 이미 시행된 경우) 휴지통으로 직접 가져가서 재활용한다. 수리하지 않으면 수리점 (재활용 대기열) 으로 가져가서 수리할 수 없습니다 (finalize 방법을 실행했지만 GC Roots 에 연결할 수 없음). 휴지통으로 가져가서 재활용합니다.
그럼 어떤 개체가 GC 루트가 될 수 있을까요?
1gt; 가상 시스템 스택의 참조 개체
2gt; 로컬 메소드 스택의 Native 메소드가 참조하는 객체
2gt; 메소드 영역 정적 속성 참조 객체
3gt; 메소드 영역 상수 참조 객체
(3) 객체 참조 분류
1gt; 강한 참조: 예를 들어, 메모리가 부족하더라도 때려도 재활용되지 않는 객체입니다.
2gt; 소프트 참조: 필수가 아닌 개체가 유용하고 메모리가 충분하면 재활용하지 않고 메모리가 부족하면 재활용합니다. 예를 들어, A 가 B 에게 돈을 빌려주고, A 가 아직 돈이 있을 때, B 는 먼저 갚지 않을 수 있고, A 는 돈이 없으니 B 는 반드시 갚아야 한다.
3gt; 약한 참조: 필수가 아닌 개체는 다음 가비지 수집 전까지 생존할 수 있습니다.
4gt; 가상 참조: 가상 참조는 재활용하기 전에 시스템 알림을 받기 위해 참조 대기열과 함께 사용해야 합니다.
다음은 Java 의 참조 유형 맵입니다.
(1) 소프트 참조 예
메모리가 충분한 경우:
실행 결과:
메모리가 부족한 경우:
실행 결과:
(2) 약한 참조 예 결과:
어쨌든 재활용
(3) 가상 참조 예:
실행 결과:
설명: 2 와 5 의 출력이 null 인 이유는 무엇입니까? 다음
3 은 null 입니다. 아직 GC 가 진행되지 않았기 때문에 객체가 참조 대기열에 추가되지 않고 GC 다음에 참조 대기열에 추가되므로 6 에 값이 있습니다.
이 가상 참조는 GC 이후 참조 대기열에 객체를 배치하므로 객체 재활용 후 해당 작업을 수행하여 객체가 참조 대기열에 있는지 여부를 확인하고 spring AOP 의 사후 알림과 유사한 사후 알림을 받을 수 있습니다.
2. 가비지 수집이 발생하는 지역
가비지 수집은 주로 힙 메모리에서 발생하며 힙 메모리는 젊은 세대와 오래된 시대로 세분화됩니다. 기본적으로 젊은 세대와 오래된 세대의 비율은 1: 2 입니다. 예를 들어 전체 힙 메모리 크기는 3G 이고 젊은 세대와 오래된 시대는 각각 젊은 세대는 Eden, S0(Survivor From) 및 S1(Survivor To) 영역, 일반 Eden: s0: S1 = 8: 1: 1 로 나뉘며, 이 비율을 변경하려면 JVM 매개 변수를 수정합니다
젊은 세대에서는 GC 가 Young GC 라고 하고, 오래된 세대에서는 GC 가 Full GC 가 되고, Young GC 가 Full GC 보다 빈번하다.
young GC:
JVM 이 시작된 후 첫 번째 GC 는 Eden 지역에 있는 개체를 S0 구역으로 이동합니다. 두 번째 GC 는 Eden 구역과 S0 과 함께 GC 입니다. 이때 살아남은 개체를 S1 구역으로 옮기고 S0 은 비웁니다. 세 번째 GC 는 Eden 구역과 S1 구역인 GC 로, 생존한 대상을 S0 구역으로 옮겨서 왕복 15 회 (기본값) 하면 생존한 대상을 노년 지역에 예치한다.
는 3 개의 통이 있는 경우 1 번과 유사합니다 (1 번 통 안의 모래는 공사장처럼 끊이지 않습니다. 당신들이 공사장에 가서 벽돌을 옮기지 않은 것은 모를 수도 있지만, 나는 정말 공사장에 가서 이사한 적이 있다), 2, 3. 1 안에 모래가 들어 있어서 모래를 미세한 모래로 체질해야 합니다.
먼저 통 1 안의 모래를 한 번 걸러낸 후 통 2 에 배치하고, 두 번째 필터는 통 1 과 통 2 안의 모래를 함께 걸러내고, 걸러낸 후 통 3 안에 넣고, 통 2 는 비운다. 세 번째 필터는 통 1 과 통 3 의 모래를 함께 걸러내고 햇볕을 쬐어 통 2 안에 넣고 통 3 은 비운다. 이렇게 왕복순환 15 회, 통 2 나 통 3 의 모래가 합격한 모래이므로 예비통에 넣어서 사용해야 합니다.
위의 중간 배럴 1 은 Eden 구역이고, 배럴 2 는 S0 구역이고, 배럴 3 은 S1 구역입니다.
3, 가비지 수집 알고리즘
는 복제 알고리즘, 태그-지우기 알고리즘, 태그-정리 알고리즘입니다.
(1) 복제 알고리즘.
메모리 영역을 같은 크기의 두 조각으로 나눕니다. 하나는 사용할 수 있고, 다른 하나는 GC 에 남아 있는 개체를 보관한 다음 사용할 조각을 지웁니다. 이렇게 순환하다.
는 신생대에 적용됩니다.
이점: 메모리 조각화가 없고 단점: 일반 메모리만 사용할 수 있습니다.
(2) 태그-정리 알고리즘.
모든 메모리 영역을 사용하여 GC 시 재활용이 필요한 메모리 영역을 먼저 표시한 다음 재활용에 동의합니다.
는 이전 시대에 적용됩니다.
단점: 많은 메모리 조각화가 발생하여 큰 객체가 메모리를 할당하지 못할 수 있습니다.
(3) 태그-정리 알고리즘.
모든 메모리 영역을 사용합니다. GC 에서는 재활용해야 할 메모리 영역을 먼저 표시한 다음 생존 객체를 잊어버리고 이동하며 경계 밖의 모든 메모리를 정리합니다.
는 이전 시대에 적용됩니다.
4, GC 로그 보기
JVM 매개 변수 활용-xx:+printGCdetails 는 GC 에 GC 로그를 인쇄할 수 있습니다.
젊은 세대 GC 로그:
오래된 GC 로그:
5, 가비지 수집기
는 주로 4 가지 유형의 컬렉터와 7 가지 주요 수집기
4 가지 범주로 구성됩니다.
(1)Serial: 단일 스레드 수집기, 작업자 스레드 차단, 모든 작업을 중지해야 합니다.
(2) 병렬 가비지 수집기: 직렬 다중 스레드 버전 및 차단 작업자 스레드
(3)CMS(ConcMarkSweep): 병렬 가비지 수집기
(4)G1: 힙을 크기가 같은 영역으로 나눈 다음 동시에 가비지 수집을 수행합니다.
기본 수집기는 어떻게 볼 수 있습니까?
JVM 매개 변수-xx:+printcommandlineflags 를 사용하면 실행 후 다음과 같은 매개 변수가 출력됩니다. Jdk1.8 의 기본값은 Parallel collector 입니다.
7 대 수집기:
(1) 직렬: 직렬 가비지 수집기, 단일 스레드 수집기. 신생대에 쓰이다. JVM 매개 변수-xx:+useSerialgc 를 사용하여 열고 연 후 Young 영역은 serial (기본 복제 알고리즘), Old 영역은 Serial Old(Serial 의 이전 버전, 하단은 태그 정리 알고리즘) 를 사용합니다.
(2)ParNew: 신세대 병렬 수집기에 사용됩니다. Serial 의 멀티스레드 버전입니다.
JVM 인수-xx:+useparnewgc, young:parnew, 복제 알고리즘을 사용합니다. Old:serialOld, 태그 정리 알고리즘. -xx: parallecgcthreads 는 기본적으로 CPU 수와 같은 스레드 재활용 수를 제한합니다. 신생대에만 병렬, 노년 대체 직렬.
(3)Parallel Scavenge: 병렬 재활용 수집기. JVM 매개 변수-xx:+useparallelgc 로 열기, young:parallel scavenge (맨 아래는 복제 알고리즘), old: parallel old (parallel 의 이전 시대 버전, 맨 아래는 태그
이 수집기에는 두 가지 장점이 있습니다.
제어 가능한 처리량: 작업자 스레드 작업 90 시간, 재활용 스레드 작업 10 시간, 즉 90 의 처리량이 있습니다.
적응 조정 정책: 매개변수를 동적으로 조정하여 최소 일시 중지 시간을 얻습니다.
(4) parallel old: parallel scavenge 의 이전 시대 버전으로 태그 정리 알고리즘을 사용합니다. JVM 매개 변수-xx:+useparalleloldgc 로 열기, 신세대 Parallel Scavenge, 노년 대체 parallel old
(5) CMS (concmarks 맨 아래는 표시 지우기 알고리즘이므로 메모리 조각이 생성되고 CPU 도 소모됩니다. 최소 재활용 일시 중지 시간을 목표로 합니다. -xx:+useconcmarksweep, 신세대 ParNew, 노년 대체 CMS. CMS 는 힙 메모리가 다 소모되기 전에 정리해야 합니다. 그렇지 않으면 실패할 경우 SerialOld 백업 수집기가 호출됩니다.
초기 태그 지정 및 태그 재지정 모두 작업자 스레드를 중지하고, 동시 태그 지정 및 동시 삭제는 작업자 스레드와 함께 작동합니다.
(6)SerialOld: 이전 세대의 직렬 수집기 (이후 Hotspot 가상 기회는 직접 제거됨).
(7) G1: G1 가비지 수집기, 알고리즘은 표시 정리이며 메모리 조각을 생성하지 않습니다. 신세대 노대에 걸쳐 있다. 가급적 높은 처리량을 실현하여 재활용 중지 시간을 단축하다.
G1 은 JVM 매개 변수-xx: maxgcpausemillis = n, n 을 사용하여 가비지 수집의 일시 중지 시간을 밀리초 단위로 정확하게 제어할 수 있습니다.
지역화된 메모리 슬라이스 Region 은 전체 힙을 같은 크기의 영역 블록 (1MB~32MB) 으로 최대 2048 개의 메모리 영역 블록으로 분할하므로 지원되는 최대 메모리는 32*2048=65535MB, 약 66mb 입니다
위 그림은 수집 전과 수집 후의 비교이며, 일부 객체는 크고 분할 후 연속적인 영역, 즉 위 그림의 Humongous 입니다.
위의 이론은 약간 지루할 수 있으며, 아래 그림은 분명합니다 (어느 정도 찾음).
다음은 전체 가비지 수집 메커니즘에 대한 마인드맵 (너무 커서 두 부분으로 나뉘어짐) 입니다.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Liusy01 에 오신 것을 환영합니다. Java 기술 및 헬스를 함께 교환하여 더 많은 건품을 얻을 수 있습니다.