JSTACK은 주어진 Java 프로세스 ID 또는 코어 파일 또는 원격 디버깅 서비스의 Java 스택 정보를 인쇄하는 데 사용됩니다. 64 비트 기계에있는 경우 "-j-d64"옵션을 지정해야합니다. Windows Jstack 사용은 다음 방법 만 지원합니다.
jstack [-l] [f] pid
Java 프로그램이 핵심 파일을 생성하기 위해 충돌하는 경우 JSTACK 도구를 사용하여 Java 스택 및 기본 스택에 대한 정보를 얻을 수있어 Java 프로그램이 어떻게 충돌하는지 쉽게 알 수 있으며 프로그램이 문제가되는 위치를 쉽게 알 수 있습니다. 또한 JSTACK 도구를 실행중인 Java 프로그램에 첨부하고 당시 실행중인 Java 프로그램의 Java 스택 및 기본 스택에 대한 정보를 볼 수 있습니다. 실행중인 Java 프로그램이 이제 Hung의 상태를 렌더링하면 Jstack이 매우 유용합니다. 프로세스가 죽은 상태에있는 경우, 스택을 -f로 플레이하도록 강제로 스택을 연주 할 수 있습니다.
덤프 파일에서주의를 기울일 가치가있는 스레드 상태는 다음과 같습니다.
교착 상태, 교착 상태 (초점)
실행 가능
대기 대기 조건 (초점)
모니터 입력 대기 (초점)
정지된
객체 대기, object.wait () 또는 timed_waiting
차단, 차단 (집중)
중지, 주차
다른 블로그에서 세 가지 시나리오를 살펴 보았습니다.
예 1 : 잠금 및 차단 대기
"RMI TCP 연결 (267865) -172.16.5.25"데몬 프리오 = 10 TID = 0x00007FD508371000 NID = 0x55AE 모니터 입력 대기 [0x000007FD4F8684000] java.lang.thread.state : blocked at at at at on in (Object Monitor) org.apache.log4j.category.callappenders (category.java:201)- org.apache.log4j.category.forcedlog (category.java:388)에서 <0x00000000acf4d0c0> (a org.apache.log4j.logger)를 잠그기 위해 기다리고 있습니다 org.apache.log4j.category.log (category.java:853) at org.apache.commons.logging.impl.log4jlogger.warn (log4jlogger.java:234) at com.tuan.core.common.lang.cache.remote.spymemcachedclient.get (spymemcachedclient.java:110)
설명 :
1) 스레드 상태가 차단되고 차단됩니다. 그것은 스레드가 리소스가 시간을 초래할 때까지 기다린다는 것을 의미합니다!
2) "<0x0000000000Acf4D0C0> 잠금 대기"는 스레드가 0x00000000ACF4D0C0 주소를 잠그기 위해 기다리고 있음을 의미합니다 (영어로 설명 할 수 있습니다.
3) 덤프 로그에서 문자열 0x00000000ACF4D0C0을 검색 한 후이 주소를 잠그기 위해 많은 수의 스레드가 있음을 발견했습니다. 로그 에서이 잠금 잠금 장치를 얻은 사람을 찾을 수 있다면 (예 : 잠금 <0x00000000acf4d0c0>) 단서를 따라갈 수 있습니다.
4) "모니터 입력 대기"는이 스레드가 동기화 된 (OBJ) {... ...} 응용 프로그램을 통해 임계 영역으로 들어가는 것을 의미합니다. 그러나 OBJ에 해당하는 모니터는 다른 스레드가 소유하고 있으므로이 스레드는 항목 세트 큐에서 기다립니다.
5) 첫 번째 줄에서 "RMI TCP 연결 (267865) -172.16.5.25"는 스레드 이름입니다. TID는 Java 스레드 ID를 나타냅니다. NID는 기본 스레드의 ID를 나타냅니다. Prio는 스레드 우선 순위입니다. [0x00007FD4F8684000]는 스레드 스택 시작 주소입니다.
예 2 : 대기 대기 및 timed_waiting
"RMI TCP 연결 (유휴)"데몬 프리오 = 10 TID = 0x00007FD50834E800 NID = 0x56B2 조건에서 대기 대기 [0x000007fd4f1a59000] java.lang.thread.state : sun.misc.unsafe.lang.thread.state : timed_waiting (주차) -Misc.unsafe.park. <0x00000000acd84de8> (java.util.concurrent.synchronousqueue $ transferstack) at java.util.concurrent.locks.locksupport.parknanos (leksupport.java:198) at java.util.concurrent.synchronousqueue $ transferstack.awaitfulfill (java.util.concurrent.synchronousqueue $ transferstack.transfer (synchronousqueue.java:323) at java.util.concurrent.synchronousqueue.poll (java.util.concurrent.threadpoolexecutor.getStask (threadpoolexecutor.java:945) at java.util.concurrent.threadpoolexecutor $ worker.run (java.lang.thread.run (Thread.java:662)의 un (threadpoolexecutor.java:907)
설명 :
1) "timed_waiting (주차)"의 Timed_waiting은 대기 상태를 말하지만 여기에 지정된 시간이 지정되며 지정된 시간에 도달 한 후 대기 상태가 자동으로 종료됩니다. 주차는 실이 매달린 것을 말합니다.
2) 스택에서 "<0x00000000ACD84DE8> (java.util.concurrent.synchronousqueue $ transferstack)를 기다리려면"대기 대기 조건 "을 결합해야합니다. 우선,이 스레드는 특정 조건이 깨어날 때까지 기다리고 있습니다. 둘째, Synchronousqueue는 대기열이 아니라 스레드간에 정보를 넘겨주는 메커니즘 일뿐입니다. 요소를 동기식에 넣으면 작업이 양도되기를 기다리는 다른 스레드가 있어야 하므로이 스레드가 기다리는 조건입니다.
3) 나는 다른 것을 볼 수 없습니다.
예 3 : obejct.wait () 및 timed_waiting
"RMI RenewClean- [172.16.5.19:28475]" "Daemon Prio = 10 TID = 0x0000000041428800 NID = 0xB09 in object.Wait () [0x00007F34F4F4F4F4F4F4F4F4F4BD00] java.lang.thread.state (Object Monitor) (java.lang.wait). 메소드)- <0x00000000AA672478> (java.lang.ref.reforecequeue.remove (referencequeue.java:118)의 <0x00000000AA672478> (java.lang.ref.referenceue $ lock)- 잠금 <0x00000000AA672478> (java.ref.Roff.Lang.Roperf.Rofrence.Rofrence.Roprence.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.Roperf.ref.ref.Roperf.Reffere. sun.rmi.transport.dgcclient $ endpointentry $ rankecleanthread.run (dgcclient.java:516) at java.lang.thread.run (Thread.java:662)
설명 :
1) "timed_waiting (객체 모니터)"이 예에서는이 스레드가 java.lang.object.wait (Long Timeout)을 호출하고 대기 상태로 들어가기 때문입니다.
2) "대기 세트"의 대기 스레드 상태는 "Object.wait ()"입니다. 스레드가 모니터를 얻고 임계 섹션을 입력하면 스레드가 계속 실행되지 않는 경우 객체의 대기 () 메소드 (일반적으로 객체 동기화 된 객체)를 호출하고 모니터를 포기하고 "대기 세트"큐를 입력합니다. 다른 스레드가 객체에서 notify () 또는 notifyall ()을 호출 할 때만 "대기 세트"큐의 스레드는 경쟁 기회를 얻지 만 하나의 스레드 만 객체의 모니터를 가져 와서 실행 상태로 돌아갑니다.
3) RMI RenewClean은 DGCClient의 일부입니다. DGC는 분산 GC, 즉 분산 가비지 수집을 말합니다.
4) 먼저 잠겨 <0x0000000AA672478> <0x0000000AA672478>에서 기다리고 있습니다. 먼저 잠그고 동일한 객체와 동일하게하는 이유는 다음과 같은 코드 구현을 보는 것입니다.
정적 개인 클래스 잠금 {}; 개인 잠금 잠금 = 새로운 잠금 (); 공개 참조 <? t> remak (long timeout) {synchronized (lock) {참조 <? t> r = allypoll ()을 확장합니다. if (r! = null) ract r; for (;;) {lock.wait (timeout); r = ReallyPoll (); …}}즉, 스레드를 실행하는 동안,이 객체의 모니터는 먼저 동기화 된 (잠금 <0x0000000AA672478)와 동기화된다. Lock.wait (timeout);에 실행되면 스레드는 모니터의 소유권을 포기하고 "대기 세트"큐에 들어갑니다 (대기 대기 <0x00000000AA672478>).
5) 스택 정보에서 판단하면 원격 물체에 대한 원격 참조가 정리되고 있습니다. 참조 된 임대가 도착했으며 분산 가비지 컬렉션이 하나씩 청소하고 있습니다.
참조:
JSTACK 분석 예제 코드를 통해 프로세스 교착 문제를 해결하십시오
요약
위의 모든 것은 Java 스레드 덤프 분석 도구 Jstack의 분석 및 사용 시나리오에 관한 것입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!