기술 탐구/백앤드

(Java) Pod 내에서 jmap를 사용하여 힙 덤프를 떠보자

지혜와 본질을 추구하는 자 2024. 6. 6. 19:32

개요

서비스를 운영하다보면 이유 모르게 OOM이 발생하거나, Heap 영역이 비정상적으로 튀는 일이 종종 있다. 이럴때 Grafana와 같은 지표로 Heap 영역을 추적할 수 있지만, Heap Dump를 통해 메모리 Leak이 발생하는 주된 원인을 찾는것이 가장 저수준으로 문제를 접근하는 방법이다.
 

들어가며

힙덤프란?

힙덤프(Heap Dump)는 자바 애플리케이션이 실행되는 동안 JVM(Java Virtual Machine)의 힙 메모리에 저장된 객체들의 상태를 캡처한 스냅샷이다.
 
메모리 사용 상태를 분석하고 메모리 누수 문제를 해결하는 데 매우 유용한 도구이며, 힙덤프를 통해 애플리케이션이 어떤 객체를 메모리에 얼마나 많이 가지고 있는지, 어떤 객체가 가장 많은 메모리를 차지하고 있는지 등을 파악할 수 있다.
 

힙덤프 방법

덤프할 어플리케이션의 PID를 확인

ps aux | grep java
[사진 1] PID 확인

쓰기 권한이 없을것을 대비하여 /tmp 경로 권한 확인

Pod 내에서 writable 디렉토리를 찾아야 한다. 일반적으로 /tmp 디렉토리는 쓰기 권한이 있다.

ls -ld /tmp

결과: drwxrwxrwt    1 root     root          4096 Jun  6 10:05 /tmp

위의 출력에서 drwxrwxrwt는 모든 사용자에게 쓰기 권한이 있음을 나타낸다.

[사진 2] /tmp 경로 확인. 일반적으로 tmp 경로에는 쓰기 권한이 있다.
 

힙덤프 명령어 입력

jmap -dump:format=b,file=/tmp/heapdump.hprof <pid>
[사진 3] 힙 덤프 명령어를 쳐서 힙덤프 파일이 만들어졌다.

로컬로 복사

kubectl cp {name-space}/{pod-name}:/tmp/heapdump.hprof ./heapdump.hprof

 

인텔리제이로 열기

힙덤프 파일을 사용하기 위해서는 VisualVM 등 여러가지 도구를 사용할 수 있지만 인텔리제이는 자체적으로 힙덤프 파일을 보기 좋게 가공해준다.

[사진 4] 힙덤프 파일을 인텔리제이로 분석

 

결과

주요 지표 설명

지표설명
Class메모리를 사용하는 클래스의 이름을 나타낸다.
Count각 클래스의 인스턴스 개수를 나타낸다.
Shallow각 객체의 직접적인 메모리 사용량을 나타낸다.
Retained해당 객체가 참조하고 있는 모든 객체들을 포함한 총 메모리 사용량을 나타낸다.

 

예시 분석

ClassCountShallowRetained분석
byte[]5798149 MB1.11 MBbyte[] 배열이 많은 인스턴스를 가지고 있으며, 큰 메모리 공간을 차지한다.
java.lang.String2638484.44 MB13.9 MBString 객체가 매우 많이 생성되었다. 이는 텍스트 데이터의 사용이 빈번함을 나타낸다.
java.util.HashMap$Node[]832897.75 MB22.42 MBHashMap의 내부 노드 배열이 많은 메모리를 차지하고 있다.

 

상세 분석 방법

  • 대상 클래스 확인:
    • Class 열을 통해 어떤 클래스가 메모리를 많이 사용하고 있는지 확인한다. 이를 통해 특정 클래스가 메모리 문제의 원인인지 파악할 수 있다.
  • 인스턴스 수 분석:
    • Count 열을 보고 각 클래스의 인스턴스 수가 적절한지 확인한다. 인스턴스 수가 비정상적으로 많다면 메모리 누수가 발생하고 있을 가능성이 있다.
  • 메모리 사용량 분석:
    • Shallow와 Retained 열을 비교하여 객체 자체의 메모리 사용량과 해당 객체가 참조하는 모든 메모리 사용량을 파악한다. 특히 Retained 크기가 큰 객체를 집중적으로 분석하는 것이 좋다.
  • 메모리 최적화:
    • 많이 사용되는 클래스와 객체를 식별한 후, 이들의 생성 및 소멸 주기를 최적화할 방법을 찾는다. 예를 들어, 캐시의 크기를 조정하거나 불필요한 객체 생성을 줄이는 방법을 고려한다.