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까지 포함해서 깊게 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java 인터프리터(Interpreter) vs JIT Compiler 완벽 이해하기 (0) | 2026.05.26 |
|---|---|
| Java JIT Compiler 동작 원리 완벽 이해하기 (0) | 2026.05.26 |
| Java GC 종류와 특징(G1GC, ZGC 등) 완벽 이해하기 (0) | 2026.05.26 |
| Java Garbage Collector(GC) 원리 완벽 이해하기 (0) | 2026.05.26 |
| Java String Pool 원리 완벽 이해하기 (0) | 2026.05.26 |
댓글