Làm thế nào để bạn buộc thu gom rác từ Shell?


106

Vì vậy, tôi đang xem một đống với jmap trên một hộp từ xa và tôi muốn buộc thu gom rác trên đó. Làm cách nào để bạn thực hiện việc này mà không cần sử dụng jvisualvm hoặc jconsole và bạn bè?

Tôi biết bạn không nên ép buộc thu gom rác - bạn chỉ nên tìm ra lý do tại sao đống rác lớn / ngày càng lớn.

Tôi cũng nhận ra rằng System.GC () không thực sự buộc thu thập rác - nó chỉ cho GC biết rằng bạn muốn nó xảy ra.

Có nói rằng có một cách để làm điều này một cách dễ dàng? Tôi đang thiếu một số ứng dụng dòng lệnh?


Câu trả lời:


25

Bạn có thể làm điều này thông qua chương trình jmxterm miễn phí .

Hãy đốt nó lên như vậy:

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

Từ đó, bạn có thể kết nối với máy chủ và kích hoạt 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

Xem các tài liệu trên trang web jmxterm để biết thông tin về cách nhúng tệp này vào các tập lệnh bash / perl / ruby ​​/ other. Tôi đã sử dụng popen2 trong Python hoặc open3 trong Perl để làm điều này.

CẬP NHẬT: đây là một lớp lót sử dụng jmxterm:

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

346

Kể từ JDK 7, bạn có thể sử dụng công cụ lệnh JDK 'jcmd' chẳng hạn như:

jcmd <pid> GC.run


22
Tại sao mọi người không nói với tôi về những điều này? :)
noahlz

2
nếu bạn nhận được "AttachNotSupportedException: Không thể mở tệp socket", hãy xem phần bổ sung của tôi cho câu trả lời này
Thomas Rebele

Và nếu bạn nhận được Explicit GC is disabled, no GC has been performedđiều đó có thể là do -XX:+DisableExplicitGCđối số VM. Xem: mail.openjdk.java.net/pipermail/serviceability-dev/2017-August/…
Eyal Roth

Điều này sẽ chỉ hoạt động cho Oracle JDK, nó sẽ không hoạt động cho jdk mở.
Ali Saleh

104

Nếu bạn chạy jmap -histo:live <pid>, điều đó sẽ buộc GC đầy đủ trên heap trước khi nó in ra bất kỳ thứ gì.


3
buộc thu gom rác trên tất cả các jav: ps axf | grep java | grep -v grep | awk '{print "jmap -histo: live" $ 1}' | sh
gtrak

1
Tài liệu đó được ghi ở đâu? Còn khi không có: sống (ví dụ: khi -F là cần thiết)?
nafg

7
Xin chào từ tương lai bí ẩn của năm 2014. jcmdhiện là công cụ phù hợp cho công việc.
noahlz

16

Bổ sung cho câu trả lời của người dùng3198490 . Chạy lệnh này có thể cung cấp cho bạn thông báo lỗi sau:

$ 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
...

Điều này có thể được giải quyết với sự trợ giúp của câu trả lời stackoverflow này

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

đâu <process_owner>là người dùng chạy quy trình với PID <pid>. Bạn có thể lấy cả hai từ tophoặchtop


Còn những điều sau đây? Điều tương tự? java.io.IOException: Operation not permitted
dhockey

Tôi chưa gặp phải thông báo lỗi này. Có thể nó hoạt động với sudo -u <process_owner> jcmd <pid> GC.run, bạn có thể thử? Lệnh này sẽ được an toàn
Thomas Rebele

Tôi sẽ có nhưng tôi không có quyền truy cập sudo trên máy đó.
dhockey

Công cụ hoạt động chính xác. Bạn không có quyền phù hợp trong hệ điều hành để thực thi nó. Điều tương tự cũng áp dụng cho các ứng dụng khác, thậm chí không sử dụng Java.
aled

6

Có một số giải pháp khác (rất nhiều giải pháp tốt ở đây đã có):

  • Viết một đoạn mã nhỏ để truy cập MemoryMBean và gọi gc().
  • Sử dụng ứng dụng khách JMX dòng lệnh (như cmdline-jmxclient , jxmterm ) và chạy gc()thao tác trên MemoryMBean

Ví dụ sau dành cho cmdline-jmxclient:

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

Điều này thật hay vì nó chỉ có một dòng và bạn có thể đưa nó vào một tập lệnh thực sự dễ dàng.


5

cho linux:

$ jcmd $(pgrep java) GC.run

jcmdđược đóng gói với JDK, $(pgrep java)lấy ID quy trình của java


Điều này sẽ chỉ hoạt động khi có một tiến trình java đang chạy. Nếu không, nó sẽ diễn giải PID thứ hai là lệnh cho jcmd mà rõ ràng là không được nhận dạng và gây ra lỗi.
Cas Eliëns

0

Tôi không nghĩ rằng có bất kỳ tùy chọn dòng lệnh nào cho giống nhau.

Bạn sẽ cần phải sử dụng jvisualvm / jconsole cho tương tự.

Tôi muốn đề nghị bạn sử dụng những công cụ này để xác định, tại sao chương trình của bạn lại tốn nhiều bộ nhớ.

Tuy nhiên, bạn không nên ép buộc GC, vì nó chắc chắn sẽ làm phiền thuật toán GC và làm cho chương trình của bạn chậm đi.


0

Nếu bạn đang sử dụng jolokia với ứng dụng của mình, bạn có thể kích hoạt bộ sưu tập rác bằng lệnh sau:

curl http://localhost:8558/jolokia/exec/java.lang:type=Memory/gc

-10

chỉ:

kill -SIGQUIT <PID>

4
Điều này sẽ kích hoạt một bãi chứa đống không phải thu gom rác
Dror Bereznitsky

ít nhất là solaris nó thực hiện một lực lượng GC.
Amin Abbaspour

2
Thậm chí không có trong Solaris, SIGQUIT sẽ không kích hoạt GC hoặc bãi chứa đống. SIGQUIT sẽ kích hoạt kết xuất luồng chỉ dành cho HotSpot. Đối với IBM JVM, nó có thể cấu hình được.
Mircea Vutcovici

Sẽ không kích hoạt GC, chỉ in dấu vết ngăn xếp.
Elad Tabak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.