JStack(스레드 덤프) 정리
1. jstack이 뭐야?
jstack = 실행 중인 Java 프로세스의 스레드 상태를 확인하는 도구
애플리케이션이 다음과 같은 문제를 일으킬 때 사용한다.
- 서버가 갑자기 느려짐
- CPU 사용량이 높음
- 특정 요청이 계속 멈춰 있음
- 스레드가 락을 기다리며 대기함
- 데드락이 의심됨
즉,
“현재 Java 애플리케이션의 스레드들이 무엇을 하고 있는가?”를 확인하는 도구
2. jstack 사용 순서
Step 1. Java 프로세스의 PID 확인
터미널에서:
jps
예:
12345 MainApplication
23456 Jps
여기서
12345
가 Java 애플리케이션의 PID(Process ID) 이다.
Step 2. jstack 실행
기본 명령어:
jstack [옵션] <PID>
예:
jstack 12345
그러면 해당 Java 프로세스의 스레드 덤프가 출력된다.
3. 주요 옵션
| 없음 | 기본 스레드 덤프 | 일반적인 스레드 상태 확인 |
| -l | Lock 정보를 상세하게 표시 | 락/데드락 분석 |
| -F | 프로세스가 응답하지 않을 때 강제로 덤프 | 일반 방법이 안 될 때 |
가장 먼저 기억할 것
jstack PID
→ 기본 스레드 상태 확인
jstack -l PID
→ Lock까지 자세히 확인
jstack -F PID
→ 응답하지 않을 때 강제로 확인
특히 **데드락을 의심한다면 -l**을 먼저 생각하면 된다.
4. 스레드 덤프에서 가장 중요한 것 = State
스레드 덤프를 보면 각각의 스레드에 상태(State) 가 나온다.
대표적으로 4가지를 기억하면 된다.
| RUNNABLE | 실행 가능한 상태 | 일하고 있음 |
| BLOCKED | Lock을 얻기 위해 대기 | 락 때문에 못 들어감 |
| WAITING | 다른 스레드의 신호를 기다림 | 누군가 깨워주길 기다림 |
| TIMED_WAITING | 일정 시간 동안 대기 | 시간을 정해놓고 기다림 |
① RUNNABLE
RUNNABLE
CPU를 사용하면서 작업하고 있거나, 실행 가능한 상태.
예를 들어:
while(true) {
// 계속 작업
}
이런 코드가 있다면 해당 스레드가 계속 RUNNABLE 상태일 수 있다.
주의할 상황
RUNNABLE + CPU 사용량 높음
→ CPU를 많이 사용하는 스레드인지 확인
단, RUNNABLE이라고 해서 반드시 현재 CPU를 실제로 사용 중이라는 뜻은 아니다. Java의 RUNNABLE에는 실행 중이거나 OS 스케줄링을 기다리는 상태가 포함될 수 있다.
② BLOCKED
BLOCKED
다른 스레드가 가지고 있는 Lock을 얻지 못해서 기다리는 상태.
예:
synchronized(lock) {
// 작업
}
A 스레드가 lock을 가지고 있는데
B 스레드가 같은 lock을 얻으려고 하면:
A → Lock 보유
B → BLOCKED
이런 상황이면?
많은 스레드가 동시에 BLOCKED
→ 특정 Lock에 스레드가 몰리고 있는지 확인
즉,
“누가 Lock을 잡고 있고, 누가 그 Lock을 기다리고 있는가?”
를 찾아야 한다.
③ WAITING
WAITING
다른 스레드가 특정 조건을 만족시키거나 신호를 줄 때까지 계속 기다리는 상태.
대표적인 예:
Object.wait()
쉽게 말하면:
“내가 알아서 다시 실행하는 게 아니라, 다른 누군가가 깨워줘야 해.”
④ TIMED_WAITING
TIMED_WAITING
정해진 시간 동안 기다리는 상태.
대표적인 예:
Thread.sleep(5000);
→ 5초 동안 대기
또는:
wait(5000);
처럼 일정 시간이 지정된 대기도 해당한다.
따라서 TIMED_WAITING 자체가 문제가 있는 것은 아니다.
5. 상태를 보고 어떻게 판단할까?
실무에서는 단순히 상태 하나만 보고 판단하면 안 된다.
CPU가 높다
RUNNABLE
↓
CPU 사용량 확인
↓
특정 스레드가 CPU를 계속 사용하는가?
↓
스택 트레이스에서 어떤 코드가 실행 중인지 확인
Lock 때문에 느리다
BLOCKED 스레드가 많음
↓
어떤 Lock을 기다리는지 확인
↓
그 Lock을 누가 가지고 있는지 확인
↓
Lock을 오래 잡고 있는 코드 확인
데드락이 의심된다
jstack -l PID
으로 Lock 정보를 포함해서 확인한다.
특히 다음과 같은 구조를 의심한다.
Thread A
↓
Lock 1 획득
↓
Lock 2 기다림
Thread B
↓
Lock 2 획득
↓
Lock 1 기다림
서로 상대방이 가진 Lock을 기다리기 때문에 둘 다 진행하지 못한다.
'【Java】' 카테고리의 다른 글
| [Redis]StringRedisTemplate (0) | 2026.07.20 |
|---|---|
| [Redis]원자적 락 (0) | 2026.07.20 |
| 멱등성(Idempotency)이 결제 시스템에 필수인 이유 (0) | 2026.07.16 |
| Result<V,E extends Throwable> 정리 (0) | 2026.04.25 |
| 함수형 예외처리 (1) | 2026.04.23 |