본문 바로가기
Spring

[Spring] 운영체제 수업 듣다 DFS 공부법 으로 GC에 오다(2)

by windy7271 2025. 4. 25.
728x90
반응형

G1GC , Java 9 부터 디폴트 GC 이다.

 

용어내용

Evacuation G1GC에서 일어나는 객체의 Copy 및 Moving을 뜻한다.
Region G1GC에서 관리하는 힙메모리 영역을 고정된 크기로 나눈 것
Humongous Region 새로 할당하는 인스턴스가 리전 하나의 메모리의 반절이 넘는경우 Humongous Region이라 칭하고 G1GC에서 별도로 관리하는 영역이 된다.
Available/Unused Region 아무것도 할당되어있지 않은 영역, Evacuating때 이주 대상이 된다.
CollectionSet (CSet) GC가 수행될 Region 집합 (타겟)CSet 내 데이터는 GC 동안 모두 비워진다. (복사 혹은 이동됨)Region 집합은 Eden, Survivor, Old Generation으로 이뤄질 수 있다.CSet이 JVM에서 차지하는 비율은 1% 이내이다.
Remembered Set (Rset) Reference를 가진 객체가 어느 Region에 있는지 기억하기 위해 사용하는 자료구조각 Region 당 하나의 RSet이 존재하며 이를 통해 Region의 병렬 및 독립된 수집을 가능하게 한다.단일 Old generation Region을 피하기 위해 cross-region references 위치를 추적하는 것 = 한 Region에서 다른 Region을 참조한다.RSet이 차지하는 비율은 5% 이내이다.
MixedCollection Young/Old 영역의 GC가 일어나는것을 Mixed GC 또는 MixedCollection이라 한다.

https://blog.leaphop.co.kr/blogs/42/G1GC_Garbage_Collector%EC%97%90_%EB%8C%80%ED%95%B4_%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0___1

 

동작 과정은 이전에 설명한것처럼 간단하게

 

1. 초기 표시(Initial Mark): 이 단계에서는 GC Root에서 시작해서 객체를 추적하며, '살아있는' 객체를 표시한다. 이 단계는 STW(Stop The World) 단계로, 모든 애플리케이션이 중단된다. 

 

2. 병렬 표시(Concurrent Mark): 초기 표시 단계에서 표시된 객체로부터 참조되는 다른 객체들을 표시한다. 이 작업은 애플리케이션의 동작과 병행해서 수행된다.

3. 재표시(Remark): 참조가 변경된 객체를 다시 추적하고 표시한다. 이 단계 역시 STW 단계로, 애플리케이션이 일시 중지된다. 

4. 청소(Cleanup): 마지막으로, 쓸모 없는 객체(가비지)를 제거하고, 메모리를 재구성한다.

5. Mixed GC : Old Generation 수집 하는 과정 , 이 단계 에서는 Old, Young 영역을 함께 수집하며, Young GC 로 충분하지 않을때 수행 된다. 이 과정에서 G1이 Old영역의 객체들을 수집하고, 힙에서의 공간회수가 이루어진다.

 

 

일단 그냥 내 서비스 코드로 해서 새로고침으로 해도 힙 메모리를 폭파시킬 수 없어 GC 테스트 코드를 만들었다.

 

System.out.println("GC 테스트 시작!");
List<byte[]> memoryHog = new ArrayList<>();

for (int i = 0; i < 1000; i++) {
    byte[] chunk = new byte[1024 * 1024]; // 1MB
    memoryHog.add(chunk);

    if (i % 10 == 0) {
        System.out.println(i + "MB 할당됨");
    }

    try {
        Thread.sleep(100); // 잠깐씩 쉬어가면서 할당
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

System.out.println("끝! 메모리 총 할당됨: " + memoryHog.size() + "MB");

 

그리고 시작해보면 된다.

 

그러면 힙 메모리가 이런식으로 보인다. 인텔리제이에서 확인할 수 있다.

아래 파랑색을 선을 보면 꼭대기에 도착했을때 그래프가 확 떨어진다.

확 떨어지는 순간이 바로 GC 가 실제로 동작해서 객체들을 회수 한 순간이다.

https://www.jetbrains.com/help/idea/cpu-and-memory-live-charts.html

 

CPU and memory live charts | IntelliJ IDEA

 

www.jetbrains.com

 

 

이 상태는 계속 위에 머물다가 갑자기 내려갔는데. 웹 사이트 상에서 다른 페이지를 들어가니 GC가 객체가 필요없다고 판단하여 다 없앤것이다.

 

GC 에 로그를 보자. 아래와 같이 추가해주면 root 밑에 로그파일을 준다.

-XX:+UseG1GC -Xlog:gc*:file=gc.log:time,level,tags 

 

 

일부로 FullGC 를 유도하기 위해 많은 메모리를 할당하고 이를 통해 GC가 어떻게 작동하는지 보려고 한다.

 

log 를 확인해 보면 메모리 사용량이 급격하게 증가하면서 G1GC 가 빈번하게 발생하고, 특히 Humongous Allocation 과 관련된 GC 이벤트도 발생한다.

 

Pause Young, Pause Young (Normal) 은 Minor GC 가 발생했다는 것이다.

 

 

2025-04-24T23:25:23.694+0900][info][gc,task     ] GC(4) Using 3 workers of 8 for evacuation
[2025-04-24T23:25:23.702+0900][info][gc,phases   ] GC(4)   Pre Evacuate Collection Set: 0.1ms
[2025-04-24T23:25:23.702+0900][info][gc,phases   ] GC(4)   Merge Heap Roots: 0.1ms
[2025-04-24T23:25:23.702+0900][info][gc,phases   ] GC(4)   Evacuate Collection Set: 7.7ms
[2025-04-24T23:25:23.702+0900][info][gc,phases   ] GC(4)   Post Evacuate Collection Set: 0.4ms
[2025-04-24T23:25:23.702+0900][info][gc,phases   ] GC(4)   Other: 0.2ms
[2025-04-24T23:25:23.702+0900][info][gc,heap     ] GC(4) Eden regions: 29->0(1)
[2025-04-24T23:25:23.702+0900][info][gc,heap     ] GC(4) Survivor regions: 7->3(5)
[2025-04-24T23:25:23.702+0900][info][gc,heap     ] GC(4) Old regions: 7->13
[2025-04-24T23:25:23.702+0900][info][gc,heap     ] GC(4) Archive regions: 2->2
[2025-04-24T23:25:23.702+0900][info][gc,heap     ] GC(4) Humongous regions: 1->1
[2025-04-24T23:25:23.702+0900][info][gc,metaspace] GC(4) Metaspace: 23924K(24256K)->23924K(24256K) NonClass: 20535K(20736K)->20535K(20736K) Class: 3389K(3520K)->3389K(3520K)
[2025-04-24T23:25:23.702+0900][info][gc          ] GC(4) Pause Young (Prepare Mixed) (G1 Evacuation Pause) 43M->17M(60M) 8.671ms
[2025-04-24T23:25:23.702+0900][info][gc,cpu      ] GC(4) User=0.01s Sys=0.00s Real=0.01s

 

로그에서 Pause Young (Prepare Mixed)와 Old Generation의 증가(Old regions: 7->13)를 보면 Mixed GC가 발생하고 있음을 알 수 있다. Mixed GC는 Young과 Old 세대를 동시에 수집하는 방식으로, 이 경우 G1 GC가 Young Generation과 함께 Old Generation도 처리하는 중임을 나타낸다.

 

[2025-04-24T23:26:59.532+0900][info][gc,start       ] GC(361) Pause Young (Concurrent Start) (G1 Humongous Allocation)
[2025-04-24T23:26:59.532+0900][info][gc,task        ] GC(361) Using 8 workers of 8 for evacuation
[2025-04-24T23:26:59.533+0900][info][gc,phases      ] GC(361)   Pre Evacuate Collection Set: 0.2ms
[2025-04-24T23:26:59.533+0900][info][gc,phases      ] GC(361)   Merge Heap Roots: 0.2ms
[2025-04-24T23:26:59.533+0900][info][gc,phases      ] GC(361)   Evacuate Collection Set: 0.4ms
[2025-04-24T23:26:59.533+0900][info][gc,phases      ] GC(361)   Post Evacuate Collection Set: 0.2ms
[2025-04-24T23:26:59.533+0900][info][gc,phases      ] GC(361)   Other: 0.1ms
[2025-04-24T23:26:59.533+0900][info][gc,heap        ] GC(361) Eden regions: 0->0(298)
[2025-04-24T23:26:59.533+0900][info][gc,heap        ] GC(361) Survivor regions: 1->1(38)
[2025-04-24T23:26:59.533+0900][info][gc,heap        ] GC(361) Old regions: 44->44
[2025-04-24T23:26:59.533+0900][info][gc,heap        ] GC(361) Archive regions: 2->2
[2025-04-24T23:26:59.533+0900][info][gc,heap        ] GC(361) Humongous regions: 1497->1497
[2025-04-24T23:26:59.533+0900][info][gc,metaspace   ] GC(361) Metaspace: 87149K(88064K)->87149K(88064K) NonClass: 74280K(74816K)->74280K(74816K) Class: 12868K(13248K)->12868K(13248K)
[2025-04-24T23:26:59.533+0900][info][gc             ] GC(361) Pause Young (Concurrent Start) (G1 Humongous Allocation) 1537M->1537M(2048M) 1.162ms
[2025-04-24T23:26:59.533+0900][info][gc,cpu         ] GC(361) User=0.01s Sys=0.00s Real=0.00s

 

1. Young Generation 의 GC 시작 

2. Concurrent Start => 병렬처리

3. G1 Humongous Allocation -> 큰 객체 할당될때 실행되는 GC가 실행

 

 

Humongous Allocation 일때도 Full GC 대신 Mixed GC로 해당 객체를 처리하려고 한다. 

Humongous Object는 Young Generation 또는 Old Generation의 여러 Regions에 걸쳐 할당되는데, G1GC는 이 큰 객체들을 처리하기 위해 추가적인 메모리 할당이나 기존의 메모리 청소를 통해 공간을 확보한다.

 

왜 ?? 

 

G1GC는 Humongous Allocation을 처리할 때 Young Generation의 GC 작업이나 Mixed GC를 사용하여 Old Generation의 Region을 관리함으로써 메모리 관리와 회수 작업을 효율적으로 처리하며, Full GC를 줄이기 위해 노력한다.

 

 

 

 

 

 

반응형

댓글