본문으로 건너뛰기
버전: 5.1.0-11.0

H7. 메모리 누수 의심 시 점검 (힙·GC·힙덤프)

Diátaxis: How-to(목표별 가이드) · 대상: 운영자 / 관리자 ← 목차로

"시간이 지날수록 응답이 느려지다 가끔 멈춘다", "재시작하면 한동안 괜찮다"는 증상은 메모리 누수의 전형입니다. 이 문서는 WAS의 JVM 탭 차트로 누수를 가려내고, 의심되면 힙 오브젝트 분석까지 파고드는 순서를 정리합니다.

"힙·GC가 무엇인가"라는 개념은 E3.2 JVM 건강을, 차트별 정확한 임계치는 R2.1 WAS 차트 — JVM을 보세요. 대상 인스턴스를 고르는 법은 H1. 모니터링 대상 좁히기에 있습니다.

여는 법 — 좌측 메뉴 ▸ WAS ▸ (인스턴스 선택) ▸ JVM

WAS JVM 탭

힙 사용률 패턴 읽기 (톱니 vs 평탄)

가장 먼저 JVM 힙 사용률(%) 차트의 모양을 봅니다. 절대값보다 모양이 먼저입니다.

모양해석
톱니(▴▾▴▾) — 올랐다가 GC 후 뚝 떨어짐이 반복정상 — 청소가 제대로 되고 있음
계단식으로 바닥이 점점 높아짐주의 — 누수 의심. GC를 해도 회수되지 않는 객체가 쌓이는 중
80% 이상에서 평탄 (거의 안 내려감)위험 — 누수 진행 가능성 높음. 곧 OutOfMemoryError 위험
JVM 메모리 사용률 % — 톱니 패턴(정상): 오르다가 GC 후 떨어짐이 반복

참고 짧은 구간만 보면 판단이 어렵습니다. H2. 기간 바꿔 보기최근 1일~1주 구간을 펼쳐, "바닥선(GC 직후 최저점)이 우상향하는가"를 확인하세요. 바닥선이 계속 올라가면 누수입니다.

이어 JVM 메모리 크기 차트에서 Used가 Max에 근접하는지 봅니다. Used 선이 Max 선에 달라붙으면 여유가 없는 상태입니다.

JVM 메모리 크기 — 누수 패턴: 사용 중인 힙의 바닥이 계단식으로 올라가다 메모리 크기(Max 4.0 GB)에 달라붙음

위 화면이 누수가 진행 중인 모양입니다. 위 정상 차트와 비교해 보세요 — 톱니는 톱니인데 GC 직후 최저점(바닥)이 매번 더 높아지고, GC가 회수하는 양(낙폭)은 점점 줄다가, 끝내 사용 중인 힙이 메모리 크기(Max) 선에 붙은 채 평탄해집니다. 이 상태가 곧 OutOfMemoryError 직전입니다.


GC 시간·횟수 확인

누수가 진행되면 JVM은 메모리를 짜내려고 GC를 더 자주, 더 오래 돌립니다. GC 시간 차트에서 두 가지를 봅니다.

  • GC 횟수가 평소보다 잦아짐 — 회수할 공간이 부족해 청소를 반복
  • 개별 GC 소요시간이 길어짐(예: 500ms 이상이 빈번) — 청소하는 동안 애플리케이션이 멈춰(Stop-the-World), 사용자가 지연·멈춤을 체감
JVM GC 시간 — 정상: 일정한 주기·비슷한 크기의 GC 스파이크
JVM GC 시간 — 누수 패턴: GC가 점점 잦아지고 길어지며, 후반부에 Old(Full) GC까지 등장해 1초를 넘김

두 화면을 비교하세요. 정상(위)은 GC가 일정한 주기로, 비슷한 크기로 돕니다. 누수(아래)는 시간이 갈수록 ① Young GC(초록) 간격이 좁아지고 ② 소요시간이 길어지며 ③ 후반부에는 Old(Full) GC(파랑)까지 등장해 1초를 넘깁니다 — 회수할 공간이 말라가면서 JVM이 점점 더 필사적으로 청소하는 모양입니다.

주의 "힙은 아직 여유 있는데 응답만 느리다"면 누수가 아니라 GC 튜닝/객체 생성 과다 문제일 수 있습니다. 이때는 힙 크기·GC 알고리즘 설정을 함께 점검합니다(R2.1 — GC 시간).


Full GC 버튼으로 누수 가려내기

힙이 점점 차오르는데 정말 누수인지, 아니면 아직 정리가 안 됐을 뿐인지 헷갈릴 때는 직접 한 번 청소시켜 보는 것이 가장 빠릅니다. JVM 탭 우측 상단의 Full GC 실행 버튼은 그 인스턴스에 전체(Full) GC를 강제로 한 번 돌립니다.

  1. 메모리 크기(또는 메모리 사용률) 차트를 띄워 둔 채, 우측 상단 Full GC 실행 버튼을 누릅니다.
  2. 버튼 직후 사용 중인 힙 선이 어떻게 움직이는지 봅니다.
Full GC 직후 모습해석
힙이 뚝 많이 떨어지고, 낮은 자리로 내려감누수 아닐 가능성 높음 — 쌓인 건 회수 가능한 임시 객체였음. 정리가 늦었을 뿐
힙이 거의 안 내려가거나, 내려간 지점이 여전히 높은 자리에 머묾누수 가능성 높음 — GC로도 못 비우는 객체가 그만큼 쌓여 있다는 뜻

핵심 누수의 정의가 바로 이것입니다 — "Full GC를 해도 회수되지 않는다." 한 번 더 확실히 하려면, 잠시 뒤 Full GC를 한 번 더 눌러 봅니다. 누를 때마다 내려간 바닥이 계속 높아진다면 누수가 진행 중입니다.

주의 Full GC는 그 순간 애플리케이션을 잠깐 멈춥니다(Stop-the-World). 트래픽이 적은 시간대에, 가능하면 한 인스턴스에만 눌러 확인하세요. 누수로 확정되면 다음 절에서 무엇이 쌓이는지를 봅니다.


힙 히스토그램·힙덤프 요청

차트로 "누수 같다"까지 좁혔으면, 무엇이 쌓이는지를 봅니다. JVM 탭의 분석 도구를 사용합니다.

  1. 힙 오브젝트 분석(Heap Object Analyze)을 실행합니다. 해당 인스턴스의 JVM 메모리 히스토그램을 수집해, 어떤 클래스의 인스턴스가 가장 많은 메모리를 차지하는지 목록으로 보여 줍니다.
  2. 시간차를 두고 두 번 수집해 비교하면 좋습니다 — 같은 클래스의 인스턴스 수·점유 메모리가 계속 늘어난다면 그 클래스가 누수 후보입니다.
  3. 필요하면 스레드 덤프 분석(Thread Dump Analyze)도 함께 받아, 특정 작업이 객체를 계속 붙잡고 있는지 확인합니다.
WAS 트러블슈팅 — 힙 오브젝트 분석: 좌측 스냅샷 목록(요청·분석·차이 분석), 우측 클래스별 바이트·인스턴스 히스토그램

위 화면처럼 좌측 스냅샷 목록에서 요청으로 히스토그램을 수집하고, 수집된 스냅샷을 골라 분석을 누르면 우측에 클래스별 점유 메모리(바이트·%)와 인스턴스 수가 큰 순서로 나열됩니다. 두 스냅샷을 골라 차이 분석을 누르면 Bytes Diff · Instances Diff 컬럼으로 증가분만 비교할 수 있습니다.

참고 히스토그램과 덤프는 사용자 요청으로 즉시 수집할 수도 있고, OOM·데드락 같은 이벤트가 발생하면 자동 수집되기도 합니다. 자동 수집분은 이벤트 목록에서 해당 이벤트를 열어 확인할 수 있습니다(R3. 이벤트 종류 레퍼런스).

주의 힙덤프 수집은 그 순간 JVM을 멈출 수 있어 부하가 큽니다. 트래픽이 적은 시간대에, 가능하면 한 인스턴스에만 요청하세요.


조치

확인된 상황1차 조치
누수 후보 클래스가 보임해당 코드의 캐시·컬렉션·리스너 등록 해제 누락 점검 (개발팀 전달)
당장 서비스가 위태로움(힙 90%+, 잦은 풀 GC)트래픽 분산 후 해당 인스턴스 순차 재시작으로 우선 안정화
Used가 Max에 자주 닿음(누수는 아님)힙 최대치(-Xmx) 상향 또는 메모리 사용 최적화
OutOfMemoryError 이미 발생이벤트에 자동 저장된 힙 객체 분석 결과부터 확인

재시작은 증상 완화일 뿐 원인 해결이 아닙니다. 누수 후보를 함께 기록해 두어야 다음에 반복되지 않습니다.


잘 안될 때

증상점검
JVM 탭에 힙 데이터가 비어 있음인스턴스가 연결돼 있는지(에이전트 상태) — H20. 에이전트 점검
힙 오브젝트 분석 버튼이 없음/안 눌림해당 인스턴스가 살아 있고 분석을 지원하는지 확인
패턴이 톱니인데도 느림누수가 아닐 수 있음 — H6. 느린 트랜잭션 원인 찾기로 전환

관련 문서