ฆ่า -3 เพื่อรับการถ่ายโอนข้อมูลเธรด java


116

ฉันใช้kill -3คำสั่งเพื่อดูเธรดดัมพ์ของ JVM ในยูนิกซ์ แต่ฉันจะหาผลลัพธ์ของkillคำสั่งนี้ได้ที่ไหน? ฉันหลงทาง!!


คุณกำลังฆ่ากระบวนการใด เป็นเซิร์ฟเวอร์แอป J2EE หรือไม่ หากเป็นกรณีนี้คุณควรหา stack trace ใน standard out
Luciano Fiandesio

ฉันกำลังฆ่ากระบวนการที่เรียกใช้คลาส java
javanerd

2
ไม่ควรเขียนเธรดดัมพ์บนคอนโซล เนื่องจากคลาส java มีคอนโซลเป็น std out
javanerd

คำตอบ:


194

คุณสามารถใช้ jstack (รวมกับ JDK) เพื่อถ่ายโอนข้อมูลเธรดและเขียนเอาต์พุตได้ทุกที่ที่คุณต้องการ สิ่งนั้นไม่พร้อมใช้งานในสภาพแวดล้อม Unix หรือไม่?

jstack PID > outfile

1
ใช่ - ณ จุดเวลาที่มีการเรียกใช้ คุณยังสามารถระบุ -l (L ตัวพิมพ์เล็ก) สำหรับรายชื่อแบบยาวที่พิมพ์ข้อมูลการล็อกเพิ่มเติมได้
Joshua McKinnon

2
จนกว่าคำสั่ง jstack จะล้มเหลวอย่างต่อเนื่องเนื่องจาก "Unable to deduce type of thread from address" ;-(
noahlz

1
หากคุณเห็นข้อผิดพลาดนั้นเราขอแนะนำให้แจ้งผู้ขายของคุณ ตัวอย่างเช่นการค้นหาอย่างรวดเร็วแสดงให้เห็นว่ามีข้อผิดพลาดที่เปิดอยู่ใน RHEL เกี่ยวกับข้อผิดพลาดนี้และ openjdk ...
Joshua McKinnon

7
เป็นที่น่าสังเกตว่า jstack ต้องการ JDK หากคุณใช้งานแอปบนเซิร์ฟเวอร์ที่ติดตั้ง JRE ไว้เท่านั้นคุณจะต้องหาวิธีอื่นในการทิ้งเธรด
jeffkempf

1
นี่คือวิธีการใช้ jstack เพื่อรับเธรดดัมพ์ของกระบวนการที่ทำงานภายใต้ผู้ใช้ที่แตกต่างกันเช่นบริการของ windows: stackoverflow.com/questions/1197912/…
Vadzim

44

เธรดดัมพ์ถูกเขียนไปยังระบบจาก VM ที่คุณรันไฟล์kill -3. หากคุณกำลังเปลี่ยนทิศทางเอาต์พุตคอนโซลของ JVM ไปยังไฟล์เธรดดัมพ์จะอยู่ในไฟล์นั้น หาก JVM กำลังทำงานในคอนโซลแบบเปิดเธรดดัมพ์จะแสดงในคอนโซล


1
มีวิธีเปลี่ยนทิศทางเอาต์พุตการถ่ายโอนข้อมูลเธรด JVM ไปยังไฟล์แยกต่างหาก ดูในคำตอบของฉัน
Vadzim

32

มีวิธีเปลี่ยนเส้นทางเอาต์พุตการถ่ายโอนข้อมูลเธรด JVM บนสัญญาณแบ่งไปยังไฟล์แยกด้วยตัวเลือกการวินิจฉัย LogVMOutput :

-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log

5
ในทางเทคนิคจะไม่ "เปลี่ยนเส้นทาง" เอาต์พุตการถ่ายโอนข้อมูลเธรด เปิดใช้งานการล็อก JVM ใน jvm.log (ซึ่งรวมเอาท์พุทการถ่ายโอนข้อมูลเธรด) แต่ kill -QUIT จะยังคงถ่ายโอนข้อมูลไปยัง stdout ของกระบวนการ (เช่นกัน) โหวตให้คำอธิบายของตัวเลือก JVM ที่คลุมเครือ :)
sqweek

25

ด้วย Java 8 ในภาพjcmdเป็นแนวทางที่ต้องการ

jcmd <PID> Thread.print

ต่อไปนี้เป็นตัวอย่างจากเอกสาร Oracle :

JDK 8 เปิดตัว Java Mission Control, Java Flight Recorder และยูทิลิตี้ jcmd สำหรับการวินิจฉัยปัญหาเกี่ยวกับแอปพลิเคชัน JVM และ Java ขอแนะนำให้ใช้ยูทิลิตี้ล่าสุด jcmd แทนยูทิลิตี้ jstack ก่อนหน้านี้เพื่อการวินิจฉัยขั้นสูงและลดค่าใช้จ่ายด้านประสิทธิภาพ

อย่างไรก็ตามการจัดส่งสิ่งนี้พร้อมกับแอปพลิเคชันอาจมีผลกระทบต่อการออกใบอนุญาตซึ่งฉันไม่แน่ใจ


1
น่าเสียดายที่jcmdล้มเหลวในการเชื่อมต่อกับกระบวนการบริการของ windows com.sun.tools.attach.AttachNotSupportedException: Insufficient memory or insufficient privileges to attachในขณะที่jstack -Fประสบความสำเร็จ: stackoverflow.com/questions/1197912/…
Vadzim

1
คุณต้องรัน jcmd <pid> Thread.dump ภายใต้ผู้ใช้เดียวกับที่กระบวนการ java มีมิฉะนั้นการเชื่อมต่อของคุณจะหลุด ดูstackoverflow.com/questions/25438983/…
Twilite

11

ในตำแหน่งเดียวกับที่วาง stdout ของ JVM หากคุณมีเซิร์ฟเวอร์ Tomcat นี่จะเป็นcatalina_(date).outไฟล์


8

เมื่อใช้ kill -3 ควรเห็นเธรดดัมพ์ในเอาต์พุตมาตรฐาน แอ็พพลิเคชันเซิร์ฟเวอร์ส่วนใหญ่เขียนเอาต์พุตมาตรฐานไปยังไฟล์แยกต่างหาก คุณควรจะพบมันเมื่อใช้ kill -3 มีหลายวิธีในการทิ้งเธรด:

  • kill -3 <PID>: ให้เอาต์พุตเป็นเอาต์พุตมาตรฐาน
  • หากมีสิทธิ์เข้าถึงหน้าต่างคอนโซลที่เซิร์ฟเวอร์กำลังทำงานอยู่สามารถใช้Ctrl+ Breakคีย์ผสมเพื่อสร้างสแต็กแทร็กบน STDOUT
  • สำหรับฮอตสปอต VM เรายังสามารถใช้jstackคำสั่งเพื่อสร้างเธรดดัมพ์ มันเป็นส่วนหนึ่งของ JDK ไวยากรณ์มีดังนี้:

    Usage:
    
    jstack [-l] <pid> (to connect to running process)
    jstack -F [-m] [-l] <pid>(to connect to a hung process)
    
     - For JRockit JVM we can use JRCMD command which comes with JDK Syntax: 
       jrcmd <jrockit pid> [<command> [<arguments>]] [-l] [-f file] [-p] -h]

ฉันมีปัญหาในการใช้ Kill -3 <PID> ทำงานได้ดี แต่ฆ่ากระบวนการหลังจากเขียนเธรดดัมพ์ไปยังคอนโซล มันควรจะทำหรือไม่?
Ashley

@ แอชลีย์ - ไม่kill -3 <PID>ควรฆ่า JVM คุณกำลังดูแอป Java ประเภทใด
slm

2

ใน Jboss คุณสามารถดำเนินการดังต่อไปนี้

nohup $JBOSS_HOME/bin/run.sh -c  yourinstancename $JBOSS_OPTS >> console-$(date +%Y%m%d).out  2>&1 < /dev/null &
kill -3 <java_pid>

การดำเนินการนี้จะเปลี่ยนเส้นทางเอาต์พุต / threadump ของคุณไปยังคอนโซลไฟล์ที่ระบุในคำสั่งด้านบน



2

ขั้นตอนที่คุณควรปฏิบัติตามหากคุณต้องการให้เธรดดัมพ์ของกระบวนการ Java แบบสแตนด์อโลนของคุณ

ขั้นตอนที่ 1:รับ ID กระบวนการสำหรับเชลล์สคริปต์ที่เรียกโปรแกรม java

linux$ ps -aef | grep "runABCD"

user1  **8535**  4369   0   Mar 25 ?           0:00 /bin/csh /home/user1/runABCD.sh

user1 17796 17372   0 08:15:41 pts/49      0:00 grep runABCD

ขั้นตอนที่ 2:รับ ID กระบวนการสำหรับเด็กที่ runABCD เรียกใช้ ใช้ PID ด้านบนเพื่อรับลูก

linux$ ps -aef | grep **8535**

user1  **8536**  8535   0   Mar 25 ?         126:38 /apps/java/jdk/sun4/SunOS5/1.6.0_16/bin/java -cp /home/user1/XYZServer

user1  8535  4369   0   Mar 25 ?           0:00 /bin/csh /home/user1/runABCD.sh

user1 17977 17372   0 08:15:49 pts/49      0:00 grep 8535

ขั้นตอนที่ 3:รับ JSTACK สำหรับกระบวนการเฉพาะ รับรหัสกระบวนการของกระบวนการ XYSServer ของคุณ เช่น 8536

linux$ jstack **8536** > threadDump.log
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.