본문 바로가기
  • Adillete
【Java】

JStack(스레드 덤프)

by 아딜렛 2026. 9. 18.

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