การรัน jmap ทำให้ไม่สามารถเปิดไฟล์ซ็อกเก็ตได้


88

ฉันต้องรันjmapเพื่อที่จะถ่ายฮีปดัมพ์ของกระบวนการของฉัน แต่jvmกลับ:

Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

ดังนั้นฉันจึงใช้-F:

./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...
  1. การใช้-F เป็นสิ่งที่เหมาะสมสำหรับการถ่ายโอนข้อมูลฮีปหรือไม่?
  2. ฉันรอ 20 นาทีแล้วยังไม่เสร็จ ความคิดใด ๆ ทำไม?

คำตอบ:


187

jmapเทียบกับjmap -Fเช่นเดียวjstackกับjstack -Fกลไกการใช้งานที่แตกต่างกันอย่างสมบูรณ์เพื่อ communcate กับเป้าหมาย JVM

jmap / jstack

เมื่อทำงานโดยไม่มี-Fเครื่องมือเหล่านี้ใช้แบบไดนามิกแนบกลไก ทำงานได้ดังนี้

  1. ก่อนที่จะเชื่อมต่อกับกระบวนการ Java 1234 ให้jmapสร้างไฟล์.attach_pid1234ที่ไดเร็กทอรีการทำงานของกระบวนการเป้าหมายหรือที่/tmp.

  2. จากนั้นjmapส่งSIGQUITไปยังกระบวนการเป้าหมาย เมื่อ JVM จับสัญญาณและพบว่า.attach_pid1234จะเริ่มAttachListenerเธรด

  3. AttachListenerเธรดสร้างซ็อกเก็ตโดเมน UNIX /tmp/.java_pid1234เพื่อฟังคำสั่งจากเครื่องมือภายนอก

  4. ด้วยเหตุผลด้านความปลอดภัยเมื่อยอมรับการเชื่อมต่อ (จากjmap) JVM จะตรวจสอบว่าข้อมูลประจำตัวของซ็อกเก็ตเพียร์เท่ากับeuidและegidของกระบวนการ JVM นั่นเป็นเหตุผลว่าทำไมjmapจะไม่ทำงานหากเรียกใช้โดยผู้ใช้รายอื่น (แม้โดยรูท)

  5. jmapเชื่อมต่อกับซ็อกเก็ตและส่งdumpheapคำสั่ง

  6. คำสั่งนี้ถูกอ่านและดำเนินการโดยAttachListenerเธรดของ JVM เอาต์พุตทั้งหมดจะถูกส่งกลับไปที่ซ็อกเก็ต เนื่องจากการถ่ายโอนข้อมูลฮีปถูกสร้างขึ้นในกระบวนการโดยตรงโดย JVM การดำเนินการจึงรวดเร็วมาก อย่างไรก็ตาม JVM สามารถทำได้ที่เซฟพอยต์เท่านั้น หากไม่สามารถเข้าถึงจุดปลอดภัยได้ (เช่นกระบวนการหยุดทำงานไม่ตอบสนองหรือกำลังดำเนินการ GC นาน) jmapจะหมดเวลาและล้มเหลว

สรุปประโยชน์และข้อเสียของ Dynamic Attach กัน

ข้อดี.

  • ฮีปดัมพ์และการดำเนินการอื่น ๆ ถูกรันร่วมกันโดย JVM ที่ความเร็วสูงสุด
  • คุณสามารถใช้เวอร์ชันใดก็ได้jmapหรือjstackเพื่อเชื่อมต่อกับ JVM เวอร์ชันอื่น ๆ

จุดด้อย

  • เครื่องมือควรถูกเรียกใช้โดยผู้ใช้ ( euid/ egid) เดียวกันกับ JVM เป้าหมาย
  • สามารถใช้ได้เฉพาะกับ JVM ที่มีชีวิตและมีสุขภาพดีเท่านั้น
  • จะไม่ทำงานหากเป้าหมาย JVM -XX:+DisableAttachMechanismจะเริ่มต้นด้วย

jmap -F / jstack -F

เมื่อทำงานกับ-Fเครื่องมือที่สลับไปโหมดพิเศษที่มีคุณสมบัติHotSpot การบริการตัวแทน ในโหมดนี้กระบวนการเป้าหมายจะถูกตรึง เครื่องมืออ่านหน่วยความจำผ่านระบบปฏิบัติการดีบักสิ่งอำนวยความสะดวกกล่าวคือptraceบน Linux

  1. jmap -Fเรียกใช้PTRACE_ATTACHJVM เป้าหมาย กระบวนการเป้าหมายถูกระงับโดยไม่มีเงื่อนไขเพื่อตอบสนองต่อSIGSTOPสัญญาณ

  2. เครื่องมืออ่านหน่วยความจำ JVM โดยใช้PTRACE_PEEKDATAไฟล์. ptraceสามารถอ่านได้ครั้งละหนึ่งคำดังนั้นจึงต้องมีการเรียกจำนวนมากเกินไปเพื่ออ่านฮีปขนาดใหญ่ของกระบวนการเป้าหมาย นี่เป็นอย่างมากและช้ามาก

  3. เครื่องมือนี้สร้างโครงสร้างภายใน JVM ขึ้นใหม่โดยอาศัยความรู้เกี่ยวกับ JVM เวอร์ชันเฉพาะ เนื่องจาก JVM เวอร์ชันต่างๆมีเค้าโครงหน่วยความจำที่แตกต่างกัน-Fโหมดจะทำงานก็ต่อเมื่อjmapมาจาก JDK เดียวกันกับกระบวนการ Java เป้าหมาย

  4. เครื่องมือจะสร้างฮีปดัมพ์เองจากนั้นเริ่มกระบวนการเป้าหมายต่อ

ข้อดี.

  • ไม่จำเป็นต้องมีความร่วมมือจาก JVM เป้าหมาย สามารถใช้งานได้แม้ในกระบวนการแขวน
  • ptraceทำงานเมื่อใดก็ตามที่สิทธิ์ระดับ OS เพียงพอ เช่นrootสามารถถ่ายโอนกระบวนการของผู้ใช้รายอื่นทั้งหมด

จุดด้อย

  • ช้ามากสำหรับกองขนาดใหญ่
  • เครื่องมือและกระบวนการเป้าหมายควรมาจาก JDK เวอร์ชันเดียวกัน
  • ไม่รับประกันจุดเซฟเมื่อเครื่องมือติดในโหมดบังคับ แม้ว่าจะjmapพยายามจัดการกรณีพิเศษทั้งหมด แต่บางครั้งก็อาจเกิดขึ้นได้ที่ JVM เป้าหมายไม่อยู่ในสถานะที่สอดคล้องกัน

บันทึก

มีวิธีที่เร็วกว่าในการทิ้งฮีปในโหมดบังคับ ขั้นแรกให้สร้าง coredump ด้วยgcoreจากนั้นเรียกใช้jmapไฟล์หลักที่สร้างขึ้น ดูคำถามที่เกี่ยวข้อง


85

ฉันเพิ่งพบว่า jmap (และน่าจะเป็น jvisualvm เมื่อใช้เพื่อสร้างฮีปดัมพ์) บังคับว่าผู้ใช้ที่รัน jmap จะต้องเป็นผู้ใช้คนเดียวกับที่รันกระบวนการพยายามที่จะดัมพ์

ในกรณีของฉัน jvm ฉันต้องการฮีปดัมพ์สำหรับกำลังรันโดยผู้ใช้ linux "jboss" ดังนั้นเมื่อsudo jmap -dump:file.bin <pid>รายงานว่า "ไม่สามารถเปิดซ็อกเก็ต:" ฉันสามารถคว้าฮีปดัมพ์ของฉันได้โดยใช้:

sudo -u jboss jmap -dump:file.bin <pid>

ฉันคิดว่ามันควรจะเป็น \ -dump: file.bin <pid> เนื่องจากคุณต้องการหลีกเลี่ยง - เมื่อส่งผ่านพารามิเตอร์จาก sudo ไปยัง jmap
อาดัม

นี่ไง! คุณต้อง sudo สำหรับ jmap และ jcmd ด้วย
xtian

ว้าว .. ใช้งานได้จริง นี่ควรเป็นคำตอบที่ยอมรับได้
Lalit Rao

3

เช่นเดียวกับที่คุณben_wingกล่าวคุณสามารถวิ่งด้วย:

sudo -u jboss-as jmap -dump:file.bin <pid>

(ในกรณีของฉันคือผู้ใช้jboss-asแต่คุณอาจเป็นjbossหรือคนอื่น ๆ ก็ได้)

แต่มันไม่เพียงพอเพราะมันขอรหัสผ่านจากฉัน ( [sudo] password for ec2-user:) แม้ว่าฉันจะสามารถเรียกใช้sudoโดยไม่ต้องแจ้งรหัสผ่านด้วยคำสั่งอื่น ๆ

ฉันพบวิธีแก้ปัญหาที่นี่และฉันต้องเพิ่มอีกsudoครั้งก่อน:

sudo sudo -u jboss-as jmap -dump:file.bin <pid>

มันทำงานร่วมกับคำสั่งอื่น ๆ เช่นjcmdและjinfoด้วย


สองเท่าsudoช่วยวันของฉัน!
Sher10ck

[root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283sudo: jmap: command not foundข้อผิดพลาดผลัด ฉันกำหนดค่าเส้นทาง java ใน. bash_profile แล้วฉันควรทำอย่างไร
เร่ร่อน

@roamer อาจเป็นเพราะเมื่อคุณเรียกใช้ในฐานะesผู้ใช้.bash_profileจะไม่มีการใช้งาน (เนื่องจากโปรไฟล์ทุบตีเกี่ยวข้องกับผู้ใช้ของคุณฉันคิดว่า) ฉันแนะนำให้รวมเส้นทาง java ในลักษณะสากลมากขึ้นหรืออาจระบุเส้นทาง java ในคำสั่งเช่นsudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283( /java/pathเส้นทาง java อยู่ที่ไหนและตรวจสอบให้แน่ใจว่ามีjmapอยู่ในนั้น )
Lucas Basquerotto

ฉันกำหนดค่าเส้นทาง java ใน /home/es/.bash_profile และฉันสามารถใช้ jmap เมื่อล็อกอินด้วยผู้ใช้ es cmd นี้ใช้sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283งานได้ ขอบคุณมาก.
เร่ร่อน

2

หากแอปพลิเคชันของคุณทำงานเป็นบริการ systemd คุณควรเปิดไฟล์บริการที่อยู่ภายใต้/usr/lib/systemd/system/และตั้งชื่อตามชื่อบริการของคุณ จากนั้นตรวจสอบว่าแอตทริบิวต์privateTmpเป็นจริงหรือไม่

หากเป็นจริงให้เปลี่ยนเป็นเท็จจากนั้นรีเฟรชบริการโดยใช้คำสั่งดังนี้: systemctl daemon-reload systemctl restart [servicename] หากคุณต้องการรัน jmap / jcmd ก่อนรีสตาร์ทคุณสามารถใช้สคริปต์ execStop ในไฟล์บริการได้ เพียงแค่ใส่คำสั่งลงไปและดำเนินการsystemctl stop [service name]


ก่อนที่ฉันจะอัปเดต /usr/lib/systemd/system/elasticsearch.service การตั้งค่า privateTmp เป็นเท็จฉันได้รับข้อผิดพลาดนี้: ไม่สามารถเปิดไฟล์ซ็อกเก็ต: กระบวนการเป้าหมายไม่ตอบสนองหรือไม่ได้โหลด HotSpot VM - แม้ว่าฉันจะเรียกใช้ jmap เป็น ผู้ใช้ elasticsearch
imdibiji
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.