[JAVA] Heap dump 분석해서 메모리 누수 잡은 방법

운영 중 메모리 사용량이 계속 증가하는데 원인을 바로 특정하기 어려운 경우가 있습니다. 이런 상황에서 heap dump를 통해 실제 객체 상태를 확인하고 메모리 누수를 추적하는 방법을 정리해보겠습니다.

Java heap dump로 메모리 누수 원인 찾는 흐름

java 환경에서 heap dump는 특정 시점의 메모리 상태를 그대로 덤프한 파일입니다. 이 파일을 분석하면 어떤 객체가 얼마나 메모리를 점유하고 있는지 확인할 수 있고, 메모리누수의 방향을 비교적 명확하게 잡을 수 있습니다.

문제가 되는 상황

메모리 누수는 보통 다음과 같은 패턴으로 드러납니다.

  • GC 이후에도 사용량이 줄지 않음
  • 시간이 지날수록 heap 사용량이 점진적으로 증가
  • 특정 기능 실행 이후 메모리 회수가 되지 않음

이 단계에서는 단순 로그만으로는 원인을 특정하기 어렵기 때문에 heap dump를 떠서 실제 객체를 보는 것이 가장 빠릅니다.

 

heap dump 생성 방법

heap dump는 JVM에서 직접 생성하거나, OOM 발생 시 자동으로 생성하도록 설정할 수 있습니다.

OOM 시 자동 생성 설정


-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump

이 설정을 넣어두면 OutOfMemoryError 발생 시 자동으로 heap dump가 생성됩니다.

수동으로 생성하는 방법


jmap -dump:live,format=b,file=heap.hprof <pid>

live 옵션을 주면 현재 살아있는 객체 기준으로 덤프를 생성합니다.

 

heap dump 분석 도구 선택

heap dump는 hprof 파일 형태로 생성되며, 일반적으로 아래 도구를 사용해 분석합니다.

  • Eclipse MAT
  • VisualVM
  • IntelliJ Profiler

이 중에서는 Eclipse MAT가 기능이 가장 풍부해서 많이 사용됩니다.

 

실제 분석 흐름

heap dump 분석은 정해진 정답이 있는 작업이라기보다, 의심되는 방향을 좁혀가는 과정에 가깝습니다.

1. Dominator Tree 확인

가장 먼저 보는 것은 Dominator Tree입니다. 이 뷰는 어떤 객체가 메모리를 많이 점유하고 있는지를 보여줍니다.

특히 retained size 기준으로 정렬하면 실제로 메모리를 많이 잡고 있는 객체를 빠르게 찾을 수 있습니다.

2. 비정상적으로 큰 컬렉션 찾기

실무에서는 List, Map 같은 컬렉션이 예상보다 커지는 경우가 많습니다.

  • HashMap 크기가 비정상적으로 큼
  • ArrayList가 계속 증가만 하고 줄지 않음

이 경우 대부분 객체가 제거되지 않고 계속 쌓이고 있는 상황입니다.

3. GC Root 참조 추적

객체가 왜 살아있는지 확인하려면 GC Root까지의 참조 경로를 봐야 합니다.

이 과정에서 static 변수나 싱글톤 객체가 의도치 않게 참조를 유지하고 있는 경우를 자주 발견합니다.

4. Leak Suspects Report 활용

MAT에서는 자동으로 Leak Suspects Report를 생성해줍니다.

이 리포트는 메모리를 많이 차지하는 객체와 의심 경로를 요약해주기 때문에 처음 분석할 때 기준점으로 사용하기 좋습니다.

 

실제 많이 나오는 메모리 누수 패턴

여러 번 분석해보면 비슷한 유형이 반복됩니다.

  • 캐시 제거 로직 누락
  • ThreadLocal 사용 후 remove 누락
  • Listener 등록 후 해제 누락
  • static 컬렉션에 계속 데이터 축적

이런 패턴은 코드상으로는 크게 문제가 없어 보이지만, 장시간 실행되면 누적되는 형태라 발견이 늦어지는 경우가 많습니다.

 

분석할 때 주의할 점

heap dump 분석은 몇 가지 주의할 부분이 있습니다.

  • 한 시점만 보면 판단이 어렵다
  • 정상적인 객체도 크게 보일 수 있다
  • GC 타이밍에 따라 결과가 달라질 수 있다

가능하다면 시간 간격을 두고 여러 dump를 비교하는 방식이 더 정확합니다.

 

정리

heap dump 분석은 메모리누수를 해결할 때 가장 직접적인 방법입니다. 로그나 지표로 추정하는 단계에서 벗어나 실제 객체를 확인할 수 있기 때문입니다.

핵심은 큰 객체를 찾고, 왜 해제되지 않는지 참조 경로를 따라가는 것입니다. 이 흐름만 익숙해지면 대부분의 메모리 문제는 방향을 잡을 수 있습니다.