วิธีการติดตามโปรแกรมจาวา?


25

ในฐานะผู้ดูแลระบบฉันบางครั้งต้องเผชิญกับสถานการณ์ที่โปรแกรมทำงานผิดปกติในขณะที่ไม่ได้สร้างข้อผิดพลาดหรือสร้างข้อความแสดงข้อผิดพลาดที่ไร้สาระ

ในอดีต - ก่อนที่จาวาจะเข้ามา - มีสองมาตรการต่อต้าน:

  1. หากไม่มีสิ่งใดช่วย - RTFM ;-)
  2. ถ้า 1. ไม่ช่วย - ติดตามการเรียกของระบบและดูว่าเกิดอะไรขึ้น

ฉันมักจะใช้strace -fสำหรับงานนี้กับ Linux (ระบบปฏิบัติการอื่นมีเครื่องมือติดตามที่คล้ายกัน) ตอนนี้ในขณะนี้มักจะทำงานได้ดีสำหรับโปรแกรมที่ล้าสมัยการติดตามจะเลือนมากเมื่อทำแบบเดียวกันบนjava -process มีการเรียกระบบจำนวนมากดูเหมือนไม่เกี่ยวข้องกับการกระทำจริงใด ๆ ที่มันเป็นเรื่องยากที่จะค้นหาผ่านการถ่ายโอนข้อมูลดังกล่าว

มีวิธีที่ดีกว่าในการทำเช่นนั้น (หากซอร์สโค้ดไม่สามารถใช้ได้)?

คำตอบ:


16

ดังที่ ckhan กล่าวถึงjstackนั้นยอดเยี่ยมเพราะมันให้การติดตามสแต็กเต็มของเธรดที่แอ็คทีฟทั้งหมดใน JVM สามารถรับได้เหมือนกันบน stderr ของ JVM โดยใช้ SIGQUIT

เครื่องมือที่มีประโยชน์อีกอย่างหนึ่งคือjmapสามารถถ่ายโอนข้อมูลฮีปจากกระบวนการ JVM โดยใช้ PID ของกระบวนการ:

jmap -dump:file=/tmp/heap.hprof $PID

ดัมพ์ฮีพนี้สามารถโหลดในเครื่องมือเช่นvisualvm(ซึ่งตอนนี้เป็นส่วนหนึ่งของการติดตั้ง Oracle java sdk มาตรฐานชื่อ jvisualvm) นอกจากนี้ VisualVM สามารถเชื่อมต่อกับ JVM ที่ทำงานอยู่และแสดงข้อมูลเกี่ยวกับ JVM รวมถึงการแสดงกราฟของการใช้งาน CPU ภายในจำนวนเธรดและการใช้ฮีป - เหมาะสำหรับการติดตามการรั่วไหล

เครื่องมืออื่นjstatสามารถรวบรวมสถิติการรวบรวมขยะสำหรับ JVM ในช่วงเวลาหนึ่งซึ่งคล้ายกับ vmstat เมื่อรันด้วยอาร์กิวเมนต์ตัวเลข (เช่นvmstat 3)

ในที่สุดก็เป็นไปได้ที่จะใช้ Java Agent เพื่อผลักดันเครื่องมือในทุกวิธีของวัตถุทั้งหมดที่โหลดเวลา ห้องสมุดjavassistสามารถช่วยทำให้เรื่องนี้ง่ายมาก ดังนั้นจึงเป็นไปได้ที่จะเพิ่มการติดตามของคุณเอง ส่วนที่ยากที่จะหาวิธีที่จะได้รับผลลัพธ์การติดตามเฉพาะเมื่อคุณต้องการและไม่ได้ตลอดเวลาซึ่งจะทำให้ JVM ช้าลงในการรวบรวมข้อมูล มีโปรแกรมที่เรียกdtraceว่าทำงานในลักษณะนี้ ฉันลองแล้ว แต่ก็ไม่ประสบความสำเร็จมาก โปรดทราบว่าเอเจนต์ไม่สามารถใช้คลาสทั้งหมดได้เนื่องจากเอเจนต์ที่ต้องการในการบู๊ต JVM ถูกโหลดก่อนที่เอเจนต์จะสามารถใช้เครื่องมือและจากนั้นสายเกินไปที่จะเพิ่มการใช้เครื่องมือให้กับคลาสเหล่านั้น

คำแนะนำของฉัน - เริ่มต้นด้วย VisualVM และดูว่าจะบอกสิ่งที่คุณต้องรู้เพราะมันสามารถแสดงกระทู้ปัจจุบันและสถิติที่สำคัญสำหรับ JVM


นี่เป็นคำถามที่ยอดเยี่ยม ฉันหวังว่าผู้คนจำนวนมากเพิ่มคำตอบด้วยความคิดอื่น ๆ เมื่อฉันถามคนที่ทำงานกับ Java เป็นเวลาหลายปีเกี่ยวกับการติดตามพวกเขาทำให้ฉันจ้องมองที่ว่างเปล่า บางทีพวกเขาอาจไม่รู้ความสุดยอดของ strace
เถ้า

10

ในสิ่งเดียวกันเมื่อการดีบักโปรแกรมที่ผิดพลาดไปแล้วบนระบบ Linux คุณสามารถใช้เครื่องมือที่คล้ายกันเพื่อดีบักการรัน JVM บนระบบของคุณ

เครื่องมือ # 1 - jvmtop

เช่นเดียวกับtopคุณสามารถใช้jvmtopเพื่อดูว่าคลาสใดที่อยู่ภายใน JVMs ที่กำลังรันบนระบบของคุณ เมื่อติดตั้งแล้วคุณจะเรียกใช้ดังนี้:

$ jvmtop.sh

เอาต์พุตมีสไตล์คล้ายกันกับเครื่องมือtop:

 JvmTop 0.8.0 alpha   amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

เครื่องมือ # 2 - jvmmonitor

อีกทางเลือกหนึ่งคือการใช้jvmmonitor JVM Monitor เป็นตัวสร้างโปรไฟล์ Java ที่รวมกับ Eclipse เพื่อตรวจสอบ CPU, เธรดและการใช้งานหน่วยความจำของแอ็พพลิเคชัน Java คุณสามารถใช้เพื่อค้นหา JVMs ที่รันอยู่บนโลคัลโฮสต์หรือสามารถเชื่อมต่อกับ JVMs รีโมตโดยใช้พอร์ต @ host

ss ของ jvmmonitor

เครื่องมือ # 3 - visualvm

visualvmอาจเป็น "เครื่องมือ" ในการเข้าถึงเมื่อทำการดีบักปัญหากับ JVM ชุดคุณลักษณะของมันค่อนข้างลึกและคุณสามารถมองลึกเข้าไปในอวัยวะภายในได้

ประสิทธิภาพของแอ็พพลิเคชันโปรไฟล์หรือวิเคราะห์การจัดสรรหน่วยความจำ:

ss ของ visualvm # 2

ใช้และแสดงการทิ้งเธรด:

ss ของ visualvm # 3

อ้างอิง


4

jstackพิจารณา ไม่ใช่การจับคู่ที่straceมากขึ้นของpstackaanalog แต่อย่างน้อยจะให้ภาพสแนปชอตทันเวลา สามารถ string'em ร่วมกันเพื่อรับร่องรอยหยาบถ้าคุณต้อง

ดูคำแนะนำได้ที่บทความ SO นี้: /programming/1025681/call-trace-in-java


2

หากคุณใช้ RHEL OpenJDK (หรือคล้ายกันประเด็นคือไม่ใช่ JDK ของ Oracle) คุณอาจใช้SystemTapสำหรับสิ่งนั้น

ฟิวส์บางคนมีการใช้งานโดยใช้ตัวเลือกบรรทัดคำสั่ง Java -XX:+DTraceMethodProbes, ,-XX:+DTraceAllocProbes -XX:+DTraceMonitorProbesโปรดทราบว่าการเปิดใช้งานโพรบเหล่านี้จะส่งผลต่อประสิทธิภาพของโปรแกรม

นี่คือตัวอย่างสคริปต์ SystemTap:

#!/usr/bin/stap

probe hotspot.class_loaded {
    printf("%12s [???] %s\n", name, class);
}

probe hotspot.method_entry, 
      hotspot.method_return {
    printf("%12s [%3d] %s.%s\n", name, thread_id, class, method);
}

probe hotspot.thread_start, 
      hotspot.thread_stop {
    printf("%12s [%3d] %s\n", name, id, thread_name);
}

probe hotspot.monitor_contended_enter, 
      hotspot.monitor_contended_exit {
    printf("%12s [%3d] %s\n", name, thread_id, class);
}

คุณยังสามารถใช้jstack()เพื่อรับ Java stack ของกระบวนการ แต่จะใช้ได้เฉพาะเมื่อคุณเริ่ม SystemTap ก่อน JVM


โปรดทราบว่า SystemTap จะติดตามทุกวิธี นอกจากนี้ยังไม่สามารถรับอาร์กิวเมนต์ของเมธอดได้ ตัวเลือกอื่นคือใช้ความสามารถของการติดตาม JVM ของตัวเองซึ่งเรียกว่า JVMTI หนึ่งในที่สุดการใช้งานที่มีชื่อเสียงเป็น JVMTI BTrace


0

คุณควรทดลองใช้Jackplayซึ่งเป็นเครื่องมือติดตาม JVM ที่ช่วยให้คุณสามารถติดตามการเข้าและออกจากวิธีการโดยไม่ต้องเปลี่ยนรหัสหรือปรับใช้ซ้ำ


คุณไม่สามารถแนบกับ JVM ที่กำลังรันอยู่ได้ นอกจากนั้น - เครื่องมือที่น่าสนใจ
นิลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.