1. GC라는 것은 무엇인가?

GC(Garbage Collection)는 Java에서 더 이상 사용되지 않는 객체를 정리해주는 메모리 관리 기능이다. 객체 그림 가능성을 고려하지 않고, 객체가 더 이상 참조되지 않는 경우 자동으로 해제한다.

대표적인 GC 알고리즘:

  • Serial / Parallel GC: Throughput 중심
  • CMS: 응답 시간 최소화
  • G1GC: Region 기능을 활용해 큰 heap에서 효율가 높은 GC

2. 실전 사례: 무한 루프 → Full GC 연속 발생 → WAS 달성

현재 Java 여보 앱에서 다음과 같은 증상이 발생했다:

  • 일정 시점 이후 CPU 100% 고정
  • GC 로그에 Full GC가 발생하고 다음과 같은 메시지 표시: Pause Full (System.gc())
  • 결과적으로 WAS가 응답 불가 상태에 빠짐

또한, G1GC 로그에서는 다음과 같은 심각한 메시지가 확인되었다:

  • Evacuation Failure: Young GC에서 객체를 이동시킬 공간이 부족
  • to-space exhausted: 힙 내에 여유 공간이 없어 객체 복사가 불가능
  • Full GC (Allocation Failure): GC가 메모리를 확보하지 못해 강제로 Full GC 발생

GC 후 사용량이 used=6283241Kused=6283241K로 변화 없이, 실질적으로 정리되지 못한 객체가 그대로 유지됨을 보여준다. 이는 힙이 포화 상태에 도달한 후에도 메모리를 회수할 수 없는 상황이었다.


3. Heap Dump 분석을 통한 문제 파악

Heap Dump 수집:

jmap -dump:format=b,file=heapdump.hprof <PID>

분석 도구: Eclipse MAT (Memory Analyzer Tool)

분석 결과:

  • 특정 VO 클래스가 List에 계속 객체를 add()하고 size를 키우는 구조 구조
  • 참조가 끊기지 않아 GC 대상이 되지 않고 메모리 문제가 발생

예시 코드:

for(int i = 0; i < list.size() ; i++){
	list.add(AAA);
    //기타 문서 처리
}

특정 시점에 진입하는 트랜잭션 일부가 이 루프에 빠져 종료되지 않음으로써, Full GC가 연속적으로 발생했고 최종적으로 WAS 다운까지 이어졌다.


4. 조치 및 확인

  1. 무한 루프에 종료 조건 추가
  2. 해당 트랜잭션을 단일 환경에서 재현 후 테스트
  3. GC 로그 확인을 위한 JVM 옵션 추가:
-XX:+PrintGCDetails -Xloggc:/var/log/gc.log

Heap 크기 일시 증설 (-Xmx10g)


5. 결론 및 교훈

  • Full GC는 결과일 뿐, 그 원인은 따로 있다.
  • Heap Dump는 실시간 분석에서 중요한 도구이다.

+ Recent posts