본문 바로가기
language/java

Java OutOfMemoryError(OOM) 원인 분석 완벽 이해하기

by 죄니안죄니 2026. 5. 26.
반응형

Java OutOfMemoryError(OOM) 원인 분석 완벽 이해하기

Java 실무에서 가장 자주 만나고 가장 무서운 장애 중 하나가 바로:

OutOfMemoryError(OOM)

입니다.

특히 운영 서버에서는:

  • API 전체 장애
  • 서버 다운
  • 응답 불가
  • GC 폭주
  • Kubernetes Pod 재시작

까지 이어질 수 있습니다.

초보 시절에는 보통:

메모리 부족 에러
 

정도로 이해하기 쉽습니다.

하지만 실제로는 OOM에도 종류가 매우 많고:

  • Heap 문제
  • Metaspace 문제
  • Thread 문제
  • Native 메모리 문제

등 원인이 완전히 다릅니다.

이번 글에서는:

  • OOM 종류
  • Heap OOM
  • Memory Leak
  • Metaspace OOM
  • Thread Leak
  • Heap Dump 분석
  • 실무 대응 전략

까지 장애 분석 관점으로 깊게 정리해보겠습니다.


1. OutOfMemoryError란?

OutOfMemoryError 는:

JVM이 더 이상 필요한 메모리를 확보하지 못하는 상태

입니다.

즉:

메모리 할당 요청
↓
사용 가능한 메모리 없음
↓
OOM 발생
 

구조.


2. OOM은 Exception이 아니다

매우 중요합니다.

OOM은:

 
java.lang.Error
 

입니다.

즉:

애플리케이션 복구 어려운 치명적 오류
 

입니다.


3. 가장 흔한 OOM 종류

대표 유형:


OOM 종류 원인
Java heap space Heap 부족
GC overhead limit exceeded GC 폭주
Metaspace 클래스 메타정보 부족
Unable to create new native thread 스레드 과다
Direct buffer memory NIO Direct Memory 부족

4. 가장 흔한 OOM: Java heap space

대표 오류:

java.lang.OutOfMemoryError:
Java heap space
 

5. Heap OOM 원인

핵심 원인:

Heap 객체 너무 많음
 

입니다.

즉:

  • 객체 과다 생성
  • 참조 유지
  • 메모리 누수

등 발생.


6. 대표적인 Heap OOM 코드

 
List<Object> list = new ArrayList<>();

while (true) {
    list.add(new Object());
}
 

결과:

객체 계속 살아있음
↓
Heap 꽉 참
↓
OOM 발생
 

7. 왜 GC가 못 지울까?

매우 중요합니다.

list가 계속 참조 유지
 

중이기 때문.

즉:

Reachable 객체
 

상태.

GC 대상 아님.


8. Memory Leak(메모리 누수)

Java도 메모리 누수 발생합니다.

많은 초보자가:

GC 있으니까 메모리 누수 없음
 

이라고 오해.


9. Java 메모리 누수의 진짜 의미

Java에서 메모리 누수란:

“안 쓰지만 참조가 남아있는 객체”
 

입니다.

즉:

  • 논리적으로는 죽어야 함
  • 하지만 reference 존재

→ GC 못 지움.


10. 실무에서 매우 흔한 메모리 누수 사례

대표 사례:


원인 설명
static Collection 객체 계속 누적
Cache 무제한 증가 메모리 고갈
ThreadLocal 누수 ThreadPool 환경
Listener 미해제 참조 유지
Session 누적 사용자 데이터 증가

11. static Collection 문제

대표 사례:

 
static List<User> users =
    new ArrayList<>();
 

여기에 계속 add.

문제:

애플리케이션 종료 전까지 살아있음
 

12. ThreadLocal 누수

실무에서 매우 중요.

예:

 
ThreadLocal<User> local
 

ThreadPool 환경에서:

Thread 재사용
↓
값 제거 안 함
↓
메모리 누수
 

가능.


13. remove() 중요

실무에서는 반드시:

 
threadLocal.remove();
 

필요.


14. GC overhead limit exceeded

대표 오류:

GC overhead limit exceeded
 

의미:

GC만 계속 하고
메모리 확보 거의 못함
 

입니다.


15. 왜 이런 현상이 생길까?

Heap 거의 가득 찬 상태에서:

GC 반복
↓
살아있는 객체 너무 많음
↓
회수 거의 못함
 

즉 JVM이 거의 죽기 직전 상태.


16. Metaspace OOM

대표 오류:

OutOfMemoryError:
Metaspace
 

17. Metaspace란?

클래스 메타데이터 저장 영역.

즉:

  • 클래스 정보
  • 메서드 정보
  • static 구조

저장.


18. Metaspace OOM 원인

대표 원인:

클래스 너무 많이 로딩
 

입니다.


19. 대표 사례: ClassLoader Leak

실무에서 매우 중요.

예:

  • WAS 재배포 반복
  • Spring DevTools
  • 동적 프록시 과다 생성

20. 왜 ClassLoader Leak이 위험할까?

ClassLoader 살아있으면:

해당 클래스 전체 GC 불가
 

즉:

  • Metaspace 증가
  • 메모리 누수

발생.


21. Unable to create new native thread

대표 오류:

Unable to create new native thread
 

22. 원인

스레드 너무 많이 생성.

예:

 
while(true) {
    new Thread(...).start();
}
 

23. 왜 위험할까?

스레드는 단순 Java 객체가 아니라:

OS Native Resource 사용
 

합니다.

즉:

  • Stack 메모리
  • OS Thread 자원

소모.


24. Thread Leak

대표 사례:

Thread 생성
↓
종료 안 됨
↓
계속 누적
 

25. Direct Buffer Memory OOM

대표 오류:

Direct buffer memory
 

26. Direct Memory란?

NIO에서 사용하는:

Heap 밖 Native 메모리
 

입니다.

대표 사용:

  • Netty
  • Kafka
  • 고성능 IO

27. 왜 Heap 충분한데 OOM 날까?

매우 중요합니다.

OOM은:

Heap만의 문제가 아니다
 

즉:

  • Native Memory
  • Metaspace
  • Thread

부족해도 OOM 가능.


28. Heap Dump란?

실무에서 매우 중요.

Heap Dump는:

Heap 메모리 상태 스냅샷

입니다.

즉:

현재 어떤 객체가 얼마나 메모리 사용 중인가
 

분석 가능.


29. Heap Dump 생성 옵션

대표 옵션:

 
-XX:+HeapDumpOnOutOfMemoryError
 

설명:


옵션 의미
-XX:+HeapDumpOnOutOfMemoryError OOM 시 Heap Dump 생성

30. Dump 저장 위치 지정

 
-XX:HeapDumpPath=/dump
 

설명:


옵션 의미
-XX:HeapDumpPath Dump 저장 위치

31. Heap Dump 분석 도구

대표 도구:


도구 특징
Eclipse MAT 가장 유명
VisualVM JVM 분석
JProfiler 상용
YourKit 상용

32. Eclipse MAT에서 보는 핵심

대표 분석 포인트:

Dominators
Retained Size
Leak Suspect
 

33. Dominator Tree란?

누가 메모리를 잡고 있는가
 

추적 구조.

실무에서 매우 중요.


34. Retained Size란?

객체 제거 시:

얼마나 메모리 회수 가능한가
 

의미.


35. GC 로그 분석도 중요

대표 옵션:

 
-Xlog:gc*
 

설명:


옵션 의미
-Xlog:gc* 상세 GC 로그 출력

36. Heap 크기 조절 옵션

 
-Xms1g -Xmx4g
 

설명:

 

옵션 의미
-Xms 초기 Heap
-Xmx 최대 Heap

37. 실무에서 진짜 중요한 것

OOM 대응 핵심은:

Heap 늘리기 전에
원인 분석 먼저
 

입니다.


38. 잘못된 대응

안 좋은 방식:

OOM 발생
↓
Heap만 무한 증가
 

근본 해결 아님.


39. 진짜 실무 대응 순서

올바른 순서:

GC 로그 확인
↓
Heap Dump 분석
↓
누수 객체 추적
↓
참조 제거
↓
필요 시 Heap 조정
 

40. 실무에서 자주 하는 실수

1) static Collection 방치

매우 흔함.


2) Cache 무한 증가

만료 정책 없는 Cache 위험.


3) ThreadLocal remove 안 함

ThreadPool 환경 위험.


4) OOM을 단순 Heap 부족으로 착각

원인은 다양함.


41. 핵심 흐름 요약

객체 생성
↓
참조 유지
↓
GC 회수 실패
↓
Heap 증가
↓
OOM 발생
 

42. 가장 중요한 핵심 한 줄

Java의 메모리 누수는
“객체를 안 쓰는데 참조를 계속 들고 있는 상태”
 

입니다.


43. 정리

OutOfMemoryError는 단순 메모리 부족 에러가 아닙니다.

실제로는:

  • Heap 구조
  • GC 동작
  • ClassLoader
  • Thread 관리
  • 객체 생명주기

전체와 연결되는 JVM 핵심 장애입니다.

특히 실무에서는:

  • Heap Dump 분석
  • Memory Leak 추적
  • ThreadLocal 누수
  • Metaspace OOM
  • GC 로그 분석

을 정확히 이해하는 것이 매우 중요합니다.

다음 글에서는:

JIT Compiler 동작 원리

를 HotSpot, C1/C2 Compiler, Tiered Compilation, Escape Analysis까지 포함해서 깊게 정리해보겠습니다.

반응형

댓글