홈 › 고급 › 10 / 10

JVM 메모리·GC·OOM 진단

힙은 어떻게 생겼고, 무엇이 남고, 터지면 어디를 보는가
섹션 7진행 0 / 10

5. 자주 하는 실수 (Tip)

  1. -Xmx 를 컨테이너 한도와 같게 설정. 비힙 영역 자리가 없어 OOM 이 아니라 OS 의 OOM killer 로 죽습니다. 로그에 자바 예외가 없으면 이 경우입니다.

  2. System.gc() 로 메모리를 확보하려 함. Full GC 를 강제해 전체가 멈춥니다. 운영에서는 -XX:+DisableExplicitGC 로 아예 막습니다. 이 레슨에서 쓴 것은 측정 목적입니다.

  3. 힙 덤프 옵션 없이 운영. OOM 은 재현이 안 됩니다. 죽은 뒤에 원인을 찾을 유일한 증거가 덤프이고, 옵션이 없으면 다음 장애까지 기다려야 합니다.

  4. GC 시간이 아니라 GC 횟수만 봄. Young GC 초당 수십 번은 정상일 수 있습니다. 문제는 Full GC 가 반복되거나 한 번의 정지가 초 단위인 경우입니다.

  5. WeakHashMap 을 캐시로 쓰고 값이 사라져 놀람. 키를 아무도 안 잡으면 GC 때마다 사라집니다. 캐시는 크기·시간 만료가 있는 LinkedHashMap 이나 Caffeine 을 씁니다.

  6. subList·substring 이 원본을 잡는다고 생각. substring 은 Java 7u6 부터 복사하므로 괜찮습니다. subList 는 뷰라 원본 리스트 전체를 붙잡으니 오래 들 거면 new ArrayList<>(list.subList(...)) 로 복사합니다.

  7. 스레드마다 큰 버퍼를 ThreadLocal 에. 스레드 풀 200개면 200벌입니다. 가상 스레드에서는 수만 벌이 됩니다.

  8. -Xlog:gc 없이 GC 문제를 추측. 로그는 비용이 거의 없습니다. 켜 두지 않으면 "느려졌다" 는 신고에 답할 자료가 없습니다.