이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • JVM Heap GC와 메모리 관찰에서 붙잡아야 할 핵심 판단 기준은 무엇인가?
  • heap 사용량은 GC 이후 추세로 본다라는 기준은 어떤 JVM/OS 신호로 확인되는가?
  • Java/Spring 코드에서 JVM Heap GC와 메모리 관찰 판단 기준은 어떤 장애 신호로 드러나는가?

개요

이 문서의 주제는 JVM Heap GC와 메모리 관찰이다. Heap 구조, GC pause, GC log, actuator metric으로 memory를 관찰하는 방법을 다룬다.

먼저 붙잡을 기준은 다음 문장이다. heap 사용량은 GC 이후 추세로 본다. 이 문서는 이 기준을 Java/Spring 실행 흐름, JVM/OS 관찰 지표, 장애 판단 순서로 연결한다.

핵심 모델

  • 판단 기준: GC는 pause와 회수 후 baseline을 함께 봐야 한다.
  • Heap 사용량은 saw-tooth 형태로 오르내릴 수 있으며, GC 후 값이 더 중요할 때가 많다.
  • Allocation rate가 높으면 leak이 없어도 GC 빈도와 CPU 사용량이 증가한다.
  • GC pause는 평균보다 p95, p99, max가 API latency와 더 잘 맞을 수 있다.
  • Heap 지표와 RSS는 같지 않으므로 JVM 지표와 OS 지표를 함께 본다.

문서별 핵심 구분

  • GC는 heap 회수를 담당하지만 pause와 CPU 비용을 만든다.
  • heap used는 GC 전보다 GC 후 추세가 중요하다.
  • allocation rate가 높으면 leak이 없어도 GC 압박이 커질 수 있다.

원리

JVM heap은 Java 객체가 할당되는 주요 영역이고 GC는 더 이상 도달할 수 없는 객체를 회수한다. 관찰할 때는 “현재 heap used”보다 GC 이후 old 영역이 어느 수준으로 돌아오는지를 본다.

GC pause는 애플리케이션 thread가 멈추는 시간으로 사용자 latency에 직접 영향을 줄 수 있다. pause가 짧아도 allocation rate가 높으면 CPU 비용과 tail latency가 커질 수 있다.

Heap 관찰은 Actuator metric, GC log, jcmd GC.heap_info, JFR을 함께 사용한다. metric은 추세를 보여 주고, GC log는 collector 동작과 pause 원인을 더 자세히 보여 준다.

JVM Heap GC와 메모리 관찰 관점에서 중요한 점은 leak과 allocation pressure를 구분하는 것이다. GC 후 바닥선이 올라가면 보관 객체를 의심하고, 바닥선은 안정적인데 GC 빈도와 CPU가 높으면 할당량이 많은 코드 경로를 의심한다.

Java/Spring 연결

  • 대량 DTO 생성, JSON 직렬화, ORM entity graph는 allocation rate를 높일 수 있다.
  • Actuator jvm.gc.pause, jvm.memory.used, GC log를 같은 시간축에 맞춘다.
  • Cache hit가 좋아 보여도 cache size가 계속 커지면 GC 후 baseline이 올라간다.
  • GC pause가 latency spike와 겹치는지 access log나 tracing과 비교한다.
  • -Xmx 변경은 pause, RSS, container limit, page cache 여유를 함께 바꾼다.

코드와 설정 예시

public OrderDto getOrder(Long id) {
    Order order = orderRepository.findById(id).orElseThrow();
    return mapper.toDto(order); // 대량 호출 시 allocation rate를 만든다.
}

예시는 leak이 없어도 객체 생성량이 많으면 GC 압박이 생긴다는 점을 보기 위한 것이다. DTO 변환, JSON 직렬화, 대량 조회, 문자열 조합은 allocation rate를 높일 수 있다.

관찰 명령

jcmd <pid> GC.heap_info
jcmd <pid> VM.flags
curl -s localhost:8080/actuator/metrics/jvm.gc.pause
curl -s localhost:8080/actuator/metrics/jvm.memory.used

JVM Heap GC와 메모리 관찰 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.

지표 해석

신호먼저 의심할 것다음 확인
GC 후 heap used가 계속 상승heap leak 또는 cache 증가class histogram, heap dump
heap은 안정적인데 RSS 상승native/direct memory, thread stackNMT, /proc/<pid>/status
Full GC와 pause 증가allocation pressure 또는 old gen 압박GC log, allocation hot spot
Swap in/out 발생OS memory pressurevmstat, container limit, OOM kill log

JVM Heap GC와 메모리 관찰에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.

장애 상황에서 보는 순서

  1. GC log와 Actuator GC pause를 API latency 시각과 맞춘다.
  2. GC 후 heap used baseline이 상승하는지 확인한다.
  3. Allocation rate와 young GC 빈도를 본다.
  4. Full GC, humongous allocation, promotion failure 같은 신호를 분류한다.
  5. Heap 조정 전 객체 생성 경로와 cache 정책을 먼저 확인한다.

이 순서는 GC를 원인인지 결과인지 구분하기 위한 루틴이다.

실전 팁

  • jvm.gc.pause는 평균보다 p95/p99와 최대값을 본다.
  • GC 후 old 영역 바닥선이 올라가는지 별도 그래프로 본다.
  • allocation rate가 높은 endpoint는 trace, profiler, JFR로 코드 경로를 좁힌다.
  • GC log는 장애 전후 collector 동작을 비교할 수 있게 보관한다.
  • heap size 변경 전에는 CPU, pause 목표, container limit을 함께 확인한다.

주니어 팁

  • JVM Heap GC와 메모리 관찰 주제는 용어 정의보다 장애 때 어떤 증거로 확인할지까지 연결해 익힌다.
  • 정상 상태에서 이 문서의 관찰 명령을 실행해 JVM Heap GC와 메모리 관찰 기준선을 남긴다.
  • 장애 시에는 JVM Heap GC와 메모리 관찰 신호가 평소 기준선에서 벗어난 시각과 방향을 먼저 본다.

시니어 팁

  • JVM Heap GC와 메모리 관찰 주제의 영향이 pool, queue, retry, timeout으로 번지는 경로를 설계 리뷰에 포함한다.
  • JVM Heap GC와 메모리 관찰 runbook에는 실행 명령, 정상 범위, 해석 기준, 금지할 대응을 같이 둔다.
  • JVM Heap GC와 메모리 관찰 판단이 container, LB, 다중 인스턴스 환경에서도 같은 의미인지 확인한다.

Guru급 팁

  • JVM Heap GC와 메모리 관찰 주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.
  • 고급 도구는 JVM Heap GC와 메모리 관찰 가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다.
  • JVM Heap GC와 메모리 관찰 조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.

위험 신호!

  • heap used 순간값만 보고 GC 문제를 판단한다.
  • GC pause p99를 보지 않고 평균만 본다.
  • allocation rate를 보지 않고 heap size만 키운다.
  • GC log 없이 collector 튜닝을 시도한다.
  • container memory limit보다 큰 heap 목표를 잡는다.

확인 질문

확인 질문

  • JVM Heap GC와 메모리 관찰 주제를 장애 중 확인할 때 Application 로그만으로 부족한 이유는 무엇인가?
    • 로그는 코드 경로를 보여 주지만 JVM Heap GC와 메모리 관찰의 JVM/OS 자원 상태, 대기 위치, 포화 방향은 별도 지표로 확인해야 하기 때문이다.
  • JVM Heap GC와 메모리 관찰 관련 설정이나 pool 크기를 바꾸기 전에 확인할 것은 무엇인가?
    • 먼저 변한 신호, 하위 자원 capacity, 변경이 완화인지 증폭인지 판단할 기준을 JVM Heap GC와 메모리 관찰 지표로 확인해야 한다.
  • JVM Heap GC와 메모리 관찰 재발을 막기 위해 장애 기록에 무엇을 남겨야 하는가?
    • 발생 시간, 영향 범위, 사용한 명령, JVM Heap GC와 메모리 관찰 핵심 지표, 원인 판단, 완화 조치, 근본 수정, 남은 리스크를 남긴다.

참고 문서