본문 바로가기
WEB,WAS/TOMCAT

스레드덤프(thread dump)

by Rainbound-IT 2022. 1. 26.
반응형

[Thread]

: 쓰레드의 개념에 대해서는 이전의 글 https://wiserloner.tistory.com/548나, 혹은 이후에 병렬 프로그래밍을 정리하며 적을 것입니다.

 

- 자바는 JVM을 사용하기에, 가장 단순한 형태의 프로그램도, 수개의 쓰레드로 이루어져 있습니다.

(내 프로그램 + JVM 자체 쓰레드)

 

(스레드 경합)

- 공유 자원에 대해서, 여러 스레드가 동시에 요구를 할 때 일어나는 현상으로, 서로 다른 쓰레드 간에 자원을 가져가기 위한 경합이 자주 발생합니다.

- 경합이 심해지면, 어느 쓰레드가 자원을 소유하지 못하고 멈춰버리는 '데드락'이 걸리기도 합니다.

- 경합은, 어느 자원에 있어서, 한 스레드가 그것을 사용함에 있어서 잠궈놓은 '락'에 대해, 다른 스레드가 기다리느라 생기는 현상이라 이해하시면 됩니다.

- 스레드 경합으로 인해 여러 문제가 일어날수 있으며, 이러한 문제를 해결하기 위하여, 스레드의 상태를 저장하고 나타내는 '스레드 덤프(Thread Dump)'를 분석합니다.

 

(스레드 동기화)

- 비동기적인 스레드간의 경합으로 일어나는 문제들을 해결하기 위해선, 각 스레드가 자주 공유하는 자원에 대해서 서로 순서를 가지고 사용하게 되는 스레드 동기화를 구현해줘야 합니다.

- 자바에서는 Monitor라는 것을 사용해서 이를 동기화합니다.

 

(Monitor)

- 자바 객체는 하나의 Monitor를 가집니다.

- 하나의 Monitor는, 하나의 스레드만 가질수 있습니다.

- 어느 한 스레드가, 해당 객체의 모니터를 가지고 있는 상태라면, 다른 스레드는 그 객체에 진입하지 못하고, 스레드가 모니터를 반납할 때까지, Wait Queue에 대기하고 있어야 합니다.

 

(스레드 상태)

- 스레드의 상태는 java.lang.Thread 클래스 내부에 State라는 이름을 가진 Enumerated Types(열거형)으로 선언되어 있습니다.

  • NEW: 스레드가 생성되었지만 아직 실행되지 않은 상태
  • RUNNABLE: 현재 CPU를 점유하고 작업을 수행 중인 상태. 운영체제의 자원 분배로 인해 WAITING 상태가 될 수도 있다.
  • BLOCKED: Monitor를 획득하기 위해 다른 스레드가 락을 해제하기를 기다리는 상태
  • WAITING: wait() 메서드, join() 메서드, park() 메서드 등를 이용해 대기하고 있는 상태
  • TIMED_WAITING: sleep() 메서드, wait() 메서드, join() 메서드, park() 메서드 등을 이용해 대기하고 있는 상태. WAITING 상태와의 차이점은 메서드의 인수로 최대 대기 시간을 명시할 수 있어 외부적인 변화뿐만 아니라 시간에 의해서도 WAITING 상태가 해제될 수 있다는 것.

(스레드 종류)

- 데몬 스레드, 비데몬 스레드가 있습니다.

- Non-daemon Thread : static void main(String[] args)에서 나온 스레드는 비데몬 스레드입니다.

- Daemon Thread : GC와 같은 JVM 보조 기능들은 모두 데몬 스레드입니다.

- 데몬 스레드는 비데몬 스레드를 보조하는 역할을 하며, 다른 비데몬 스레드가 없다면 데몬 스레드는 동작을 중지합니다.

- main 메서드가 실행되는 스레드를 HotSpot VM에서는 VM Thread라고 부릅니다.

 

(스레드 덤프 획득하기)

- 자바로 만든 웹 어플리케이션 등이 늦게 동작한다면, 그 어플리케이션이 실행시키는 스레드의 상태를 살펴봐야 합니다.

- 바로 그러한 정보를 가진 것이 스레드 덤프입니다.

- 스레드 덤프의 획득은, 획득할 당시의 스레드 상태만 알 수 있기 때문에 스레드 상태 변화를 확인하려면 5초 정도의 간격으로 5~10회 정도 획득하는 것이 좋습니다.

 

- Jstack 사용하기 : 

1. CMD 창에,

jps -v

명령어를 입력하여, 돌아가고 있는 JVM 어플리케이션의 PID를 찾습니다.

 

2. jps로 추출한 PID를 인수로 넣어 jstack을 실행하면 스레드 덤프를 획득합니다.

jstack 18812 

 

- Java VisualVM 사용하기

: Java VisualVM은, 스레드 덤프를 확인할수 있는 GUI 프로그램입니다.

https://d2.naver.com/helloworld/10963

왼쪽 패널은 실행 중인 프로세스의 목록입니다. 이 목록에서 정보를 원하는 프로세스를 클릭한 다음 오른쪽 패널에서 Threads 탭을 선택하면 스레드의 정보를 실시간으로 확인할 수 있습니다. 스레드 덤프를 파일로 저장하려면 스레드 정보가 나타나는 화면 오른쪽 위의 Thread Dump 버튼을 클릭하면 됩니다.

 

- kill 명령어를 사용하는 방법

: Linux 환경에서는 kill 명령어로 스레드 덤프를 획득할 수 있습니다. kill 명령어의 인수로 사용할 PID는 ps -ef | grep java 명령어로 확인합니다.

[user@linux ~]$ ps -ef | grep java


user 25780 1 0 11:23 pts/3 00:00:00 /home1/user/java/jdk1.6.0_24/bin/java -Djava.util.logging.config.file=/home1/user/java/apps/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dfile.encoding=UTF-8 -XX:PermSize=256m -XX:MaxPermSize=256m -Xms1024m -Xmx1024m -server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home1/user/java/apps/tomcat/logs -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseConcMarkSweepGC -Djava.endorsed.dirs=/home1/user/java/apps/tomcat/common/endorsed -classpath :/home1/user/java/apps/tomcat/bin/bootstrap.jar:/home1/user/java/apps/tomcat/bin/commons-logging-api.jar -Dcatalina.base=/home1/user/java/apps/tomcat -Dcatalina.home=/home1/user/java/apps/tomcat -Djava.io.tmpdir=/home1/user/java/apps/tomcat/temp org.apache.catalina.startup.Bootstrap start


user 26335 25361 0 15:49 pts/3 00:00:00 grep java

ps 명령어로 확인한 PID를 다음과 같이 kill 명령어의 인수인 -3(또는 -QUIT -SIGQUIT)과 함께 사용하여 스레드 덤프를 획득합니다.

[user@linux ~]$ kill -3 25780 

 

//저는 아래 출처를 통해 공부중입니다.

본격적인 스레드 덤프 분석 관련해서는 추후 공부를 하고 실습하며 정리할 예정입니다.

//출처 : https://d2.naver.com/helloworld/10963

 

 

 

1. 들어가며

1-1. 스레드의 종류

  • Daemon Thread
    • 작업을 돕는 보조적인 역할을 수행하는 쓰레드 (GC 도 여기에 해당)
    • 프로세스 종료시 데몬 쓰레드는 강제적으로 자동종료
    • 언제든지 종료가 되어도 상관없는 작업 시에 사용 (그래서 주로 데몬쓰레드를 쓴다)
    • Thread t = new Thread(); t.setDaemon(true); 로 설정가능
  • Non-Daemon Thread
    • 실제 주 작업을 하는 스레드
    • 프로세스 종료시 논데몬 쓰레드가 살아있는 경우 종료 불가능 (가끔 톰캣을 종료했지만 안꺼져서 kill 해야되는 이유)
    • 매우 중요한 데이터 처리시에 사용하는 것이 일반적

1-2. 스레드덤프를 추출해보면 좋은 상황

  1. 모든 시스템에 응답이 없을 때
  2. 사용자 수가 많지 않은데 CPU사용량이 높을때
  3. 특정어플리케이션 수행 시 응답이 없을때
  4. 간헐적으로 응답이 느릴때
  5. 서비스 실행시간이 길어질수록 응답시간이나 cpu 사용량이 늘어날떄 등등

1-3. 멀티스레드 프로그래밍을 안하는데?

java.lang.Thread 를 이용해서 직접 개발하지 않더라도 이미 프레임워크, WAS, 라이브러리에서 내부적으로 사용하고 있다.

만약 라이브러리에서 문제가 생긴다면?? 이럴때 스레드덤프를 쓸 줄 안다면 유용할 것이여~~

2. 스레드덤프 생성하기

  • OS단에서
    • 리눅스 : kill -3 [PID]
    • 윈도우 : Ctrl + Break
  • java단에서 (jps -v 로 java 프로세스 확인)
    • jstack [PID] (jstack으로 반응이 없는 경우 –F 옵션)
    • jcmd [PID] Thread.print (jdk7 이후 등장)
      • jcmd [PID] help 로 명령어 확인 가능, 직관적임
  • 이때 시간이 있다면 텀을 두고 3~4장을 떠두는게 좋다.

3. 스레드덤프를 읽어보자

  • 스레드이름
    • lang.Thread 클래스로 생성하면 'Thread-숫자' 형식으로 생성된다.
    • DefaultThreadFactory 를 사용하면 pool-숫자-thread-숫자 형식으로 생성된다.
    • 하지만 이런 디폴트이름들로 쓰레드가 가득하다면 덤프를 읽기가 매우 힘들다. 멀티스레드 프로그래밍을 직접할 경우, setName을 이용해서 직관적인 스레드명을 써주는게 좋다.
  • 우선순위 : 스레드 우선순위 (스펙에서도 안중요하다고 함)
  • 스레드 아이디
    • 16진수
    • tid : 자바레벨 쓰레드ID, 자바프로세스마다 1부터 시작. 겹칠수 있겠다.
      • ThreadMXBean과 ThreadInfo 을 이용하여 정보 획득 가능
    • nid : 네이티브 쓰레드ID, OS영역이고 유니크함
      • ps 명령어를 이용해 cpu 사용율 등도 알 수 있음
  • 스레드 상태
    • runnable
    • blocked
      • deadlock
    • wait
  • 스레드 콜스택

4. 스레드덤프의 각종 도구

4-1. JVisualVM

jdk 설치할 때 같이 설치되므로, 환경변수가 잘 잡혀있다면 jvisualvm 이라고 치면 바로 뜬다.

4-2. TDA

  • Thread Dump Analyzer
  • 오래되고 jvm 별로 포맷이 달라 안읽히는 경우도 있음

4-3. fastThread 사이트

fastthread.io



출처: https://sjh836.tistory.com/151 [빨간색코딩]

 

 

 

 

반응형

'WEB,WAS > TOMCAT' 카테고리의 다른 글

EJB란 무엇인가?  (0) 2023.07.06
Tomcat 9 관리자 접속하기 및 사용하지 않는 이유  (0) 2023.02.23
Apache 2.4.X 설치 및 실행 for Windows 11  (0) 2022.12.08
apache virtual host 설정  (0) 2022.03.30
AJP  (0) 2022.01.26

댓글