คุณบังคับให้เก็บขยะจากเชลล์ได้อย่างไร?


106

ดังนั้นฉันกำลังดูฮีปที่มี jmap บนกล่องระยะไกลและฉันต้องการบังคับให้รวบรวมขยะในนั้น คุณจะทำอย่างไรโดยไม่ต้องเข้าไปใน jvisualvm หรือ jconsole และเพื่อน ๆ ?

ฉันรู้ว่าคุณไม่ควรบังคับให้เก็บขยะ - คุณควรหาสาเหตุว่าทำไมกองถึงใหญ่ / โต

ฉันยังตระหนักดีว่า System.GC () ไม่ได้บังคับให้เก็บขยะจริง ๆ - เพียงแค่บอก GC ว่าคุณต้องการให้เกิดขึ้น

ต้องบอกว่ามีวิธีทำง่ายๆนี้หรือไม่? แอพบรรทัดคำสั่งบางอย่างฉันหายไป?


ไม่เหมือนกับstackoverflow.com/questions/1481178/…
Raedwald

คำตอบ:


25

คุณสามารถทำได้ผ่านโปรแกรมjmxtermฟรี

จุดไฟขึ้นดังนี้:

java -jar jmxterm-1.0-alpha-4-uber.jar

จากนั้นคุณสามารถเชื่อมต่อกับโฮสต์และทริกเกอร์ GC:

$>open host:jmxport
#Connection to host:jmxport is opened
$>bean java.lang:type=Memory
#bean is set to java.lang:type=Memory
$>run gc
#calling operation gc of mbean java.lang:type=Memory
#operation returns: 
null
$>quit
#bye

ดูเอกสารในเว็บไซต์ jmxterm สำหรับข้อมูลเกี่ยวกับการฝังสิ่งนี้ใน bash / perl / ruby ​​/ scripts อื่น ๆ ฉันเคยใช้ popen2 ใน Python หรือ open3 ใน Perl เพื่อทำสิ่งนี้

UPDATE:นี่คือซับเดียวโดยใช้ jmxterm:

echo run -b java.lang:type=Memory gc | java -jar jmxterm-1.0-alpha-4-uber.jar -n -l host:port

346

ตั้งแต่ JDK 7 คุณสามารถใช้เครื่องมือคำสั่ง JDK 'jcmd' เช่น:

jcmd <pid> GC.run


22
ทำไมคุณไม่บอกฉันเกี่ยวกับสิ่งเหล่านี้! :)
noahlz

2
หากคุณได้รับ "AttachNotSupportedException: ไม่สามารถเปิดไฟล์ซ็อกเก็ต" โปรดดูคำตอบเพิ่มเติมของฉัน
Thomas Rebele

และหากคุณได้รับExplicit GC is disabled, no GC has been performedอาจเป็นเพราะ-XX:+DisableExplicitGCอาร์กิวเมนต์ VM ดู: mail.openjdk.java.net/pipermail/serviceability-dev/2017-August/…
Eyal Roth

สิ่งนี้จะใช้ได้กับ Oracle JDK เท่านั้นซึ่งจะไม่สามารถใช้ได้กับ open-jdk
Ali Saleh

104

หากคุณเรียกใช้jmap -histo:live <pid>นั่นจะบังคับให้ GC เต็มบนฮีปก่อนที่จะพิมพ์อะไรออกมา


3
บังคับรวบรวมขยะใน javas ทั้งหมด: ps axf | grep java | grep -v grep | awk '{print "jmap -histo: live" $ 1}' | sh
gtrak

1
เอกสารนั้นอยู่ที่ไหน? สิ่งที่เกี่ยวกับ without: live (เช่นเมื่อต้องการ -F)?
nafg

7
สวัสดีจากอนาคตอันลึกลับของปี 2014 jcmdตอนนี้เป็นเครื่องมือที่เหมาะสมสำหรับงานนี้
noahlz

16

นอกเหนือจากคำตอบของuser3198490 การรันคำสั่งนี้อาจทำให้คุณได้รับข้อความแสดงข้อผิดพลาดต่อไปนี้:

$ jcmd 1805 GC.run    
[16:08:01]
1805:
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
...

สิ่งนี้สามารถแก้ไขได้ด้วยความช่วยเหลือของคำตอบ stackoverflow นี้

sudo -u <process_owner> jcmd <pid> GC.run

ที่<process_owner>เป็นผู้ใช้ที่รันกระบวนการที่มี <pid>PID คุณสามารถรับทั้งจากtopหรือhtop


สิ่งต่อไปนี้คืออะไร? เหมือนกันมั้ย? java.io.IOException: Operation not permitted
dhockey

ฉันยังไม่พบข้อความแสดงข้อผิดพลาดนี้ อาจใช้ได้กับsudo -u <process_owner> jcmd <pid> GC.runคุณลองดูไหม คำสั่งควรปลอดภัย
Thomas Rebele

ฉันจะมี แต่ฉันไม่มีสิทธิ์เข้าถึง sudo บนเครื่องนั้น
dhockey

เครื่องมือทำงานได้อย่างถูกต้อง คุณไม่มีสิทธิ์ที่ถูกต้องในระบบปฏิบัติการเพื่อดำเนินการ เช่นเดียวกับแอปพลิเคชันอื่น ๆ แม้ว่าจะไม่ได้ใช้ Java
เบียร์

6

มีวิธีแก้ปัญหาอื่น ๆ อีกสองสามวิธี (มีหลายวิธีที่ดีอยู่แล้ว):

  • เขียนโค้ดเล็กน้อยเพื่อเข้าใช้งานMemoryMBeanแล้วโทรgc().
  • ใช้ไคลเอ็นต์ JMX แบบบรรทัดคำสั่ง (เช่นcmdline-jmxclient , jxmterm ) และรันการgc()ดำเนินการบน MemoryMBean

ตัวอย่างต่อไปนี้ใช้สำหรับ cmdline-jmxclient:

$ java -jar cmdline-jmxclient-0.10.3.jar - localhost:3812 'java.lang:type=Memory' gc

นี่เป็นสิ่งที่ดีเพราะเป็นเพียงบรรทัดเดียวและคุณสามารถใส่ลงในสคริปต์ได้อย่างง่ายดาย


5

สำหรับ linux:

$ jcmd $(pgrep java) GC.run

jcmdบรรจุด้วย JDK $(pgrep java)รับ ID กระบวนการของ java


สิ่งนี้จะใช้ได้ก็ต่อเมื่อดูเหมือนว่ามีกระบวนการ java หนึ่งกระบวนการทำงานอยู่ มิฉะนั้นจะตีความ PID ที่สองเป็นคำสั่งสำหรับ jcmd ซึ่งไม่รู้จักอย่างชัดเจนและทำให้เกิดข้อผิดพลาด
Cas Eliëns

0

ฉันไม่คิดว่าจะมีตัวเลือกบรรทัดคำสั่งเหมือนกัน

คุณจะต้องใช้ jvisualvm / jconsole เหมือนกัน

ฉันอยากจะแนะนำให้คุณใช้เครื่องมือเหล่านี้เพื่อระบุตัวตนเพราะเหตุใดโปรแกรมของคุณจึงมีหน่วยความจำสูง

อย่างไรก็ตามคุณไม่ควรบังคับ GC เพราะมันจะรบกวนอัลกอริทึม GC และทำให้โปรแกรมของคุณช้า



-10

แค่:

kill -SIGQUIT <PID>

4
สิ่งนี้จะทำให้กองขยะไม่ใช่การเก็บขยะ
Dror Bereznitsky

อย่างน้อยก็คือโซลาริสมันสร้างแรง GC
Amin Abbaspour

2
แม้กระทั่งใน Solaris SIGQUIT จะไม่ทริกเกอร์ทั้ง GC หรือฮีปดัมพ์ SIGQUIT จะทริกเกอร์การถ่ายโอนข้อมูลเธรดสำหรับ HotSpot เท่านั้น สำหรับ IBM JVM สามารถกำหนดค่าได้
Mircea Vutcovici

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