서버를 운영하다보면 힙 설정을 하였는데 k8s pod OOM kill이 나기도 하고, jcmd로 본 JVM 메모리 사용량과 top으로 본 Java 프로세스의 메모리가 차이가 나기도 한다.
Java 프로세스가 사용하는 메모리는 단순히 -Xmx로 정한 힙 크기로 끝나지 않는다. JVM은 메모리를 예약(Reserved)하고, 그 중 일부를 커밋(Committed) 해서 논리적으로 확보한 뒤, 필요할 때마다 OS가 실제 물리 메모리(RAM)를 할당하는 과정을 거친다.
즉, JVM과 OS는 다른 기준으로 메모리를 바라본다. JVM은 “쓸 수 있는 공간”을 기준으로, OS는 “이미 매핑된 페이지”를 기준으로 계산하는 것이다.
이 글에서는 JVM의 메모리 관리 단계를 Reserved → Committed → RSS 순서로 정리하면서, 왜 이 세 값이 다르게 보이는지, 그리고 그 차이가 주는 영향에 대해서 정리해본다.
JVM 내부에는 여러 메모리 영역이 존재하고, 각 영역은 역할과 관리 방식이 다르다.
Heap, Metaspace, Method Area, Stack, Native 영역 등이 존재하는데 그 중에서도 가장 큰 비중을 차지하는 곳이 Heap 영역이다.
Heap 영역은 -Xms, -Xmx 옵션으로 크기를 조절하며, JVM은 이 힙 메모리를 OS로부터 받아올 때 세 단계를 거친다.
[1] Reserved -> [2] Committed -> [3] RSS