Jak wymusić zbieranie śmieci z powłoki?


106

Tak więc patrzę na stertę z jmap na zdalnym pudełku i chcę wymusić na niej zbieranie śmieci. Jak to zrobić bez zaglądania do jvisualvm lub jconsole i przyjaciół?

Wiem, że nie powinieneś ćwiczyć wymuszania zbierania śmieci - powinieneś po prostu dowiedzieć się, dlaczego sterta jest duża / rośnie.

Zdaję sobie również sprawę, że System.GC () w rzeczywistości nie wymusza czyszczenia pamięci - po prostu mówi GC, że chcesz, aby to nastąpiło.

Powiedziawszy, że można to łatwo zrobić? Brakuje mi jakiejś aplikacji wiersza poleceń?


Odpowiedzi:


25

Możesz to zrobić za pomocą bezpłatnego programu jmxterm .

Odpal to tak:

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

Stamtąd możesz połączyć się z hostem i uruchomić 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

Zajrzyj do dokumentacji na stronie jmxterm, aby uzyskać informacje na temat osadzania tego w skryptach bash / perl / ruby ​​/ innych. Użyłem do tego popen2 w Pythonie lub open3 w Perlu.

AKTUALIZACJA: oto jedna linijka wykorzystująca jmxterm:

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

346

Od JDK 7 możesz użyć narzędzia poleceń JDK „jcmd”, takiego jak:

jcmd <pid> GC.run


22
Dlaczego nie powiecie mi o tych rzeczach ?! :)
noahlz

2
jeśli pojawi się „AttachNotSupportedException: Unable to open socket file”, zobacz mój dodatek do tej odpowiedzi
Thomas Rebele,

A jeśli otrzymujesz Explicit GC is disabled, no GC has been performed, może to być spowodowane -XX:+DisableExplicitGCargumentem VM. Zobacz: mail.openjdk.java.net/pipermail/serviceability-dev/2017-August/…
Eyal Roth

Będzie to działać tylko dla Oracle JDK, nie będzie działać dla open-jdk.
Ali Saleh

104

Jeśli uruchomisz jmap -histo:live <pid>, wymusi to pełny GC na stercie, zanim cokolwiek wydrukuje.


3
wymuś czyszczenie pamięci na wszystkich javas: ps axf | grep java | grep -v grep | awk '{print "jmap -histo: live" $ 1}' | sh
gtrak

1
Gdzie to jest udokumentowane? A co bez: na żywo (np. Gdy potrzebne jest -F)?
nafg

7
Witam z tajemniczej przyszłości 2014r. jcmdJest teraz odpowiednim narzędziem do tego zadania.
noahlz

16

Dodatek do user3198490 odpowiedź „s. Uruchomienie tego polecenia może spowodować wyświetlenie następującego komunikatu o błędzie:

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

Można to rozwiązać za pomocą tej odpowiedzi na temat przepełnienia stosu

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

gdzie <process_owner>jest użytkownikiem, który uruchamia proces z PID <pid>. Możesz uzyskać oba z toplubhtop


A co z następującymi? Ta sama rzecz? java.io.IOException: Operation not permitted
dhockey

Nie napotkałem jeszcze tego komunikatu o błędzie. Może to działa sudo -u <process_owner> jcmd <pid> GC.run, czy mógłbyś spróbować? Polecenie powinno być bezpieczne
Thomas Rebele

Miałbym, ale nie mam dostępu do sudo na tym komputerze.
dhockey

Narzędzie działa poprawnie. Po prostu nie masz odpowiednich uprawnień w systemie operacyjnym, aby go wykonać. To samo dotyczy innych aplikacji, nawet nie korzystających z Javy.
aled

6

Jest kilka innych rozwiązań (już tutaj wiele dobrych):

  • Napisz mały kod, aby uzyskać dostęp do MemoryMBean i zadzwoń gc().
  • Używając klienta JMX wiersza poleceń (takiego jak cmdline-jmxclient , jxmterm ) i uruchom gc()operację na MemoryMBean

Poniższy przykład dotyczy cmdline-jmxclient:

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

Jest to fajne, ponieważ jest to tylko jedna linia i można ją bardzo łatwo umieścić w skrypcie.


5

dla linuxa:

$ jcmd $(pgrep java) GC.run

jcmdjest spakowany z JDK, $(pgrep java)pobiera identyfikator procesu java


To zadziała tylko wtedy, gdy wygląda na to, że jest uruchomiony jeden proces Java. W przeciwnym razie zinterpretuje drugi PID jako polecenie dla jcmd, które oczywiście nie jest rozpoznane i zgłosi błąd.
Cas Eliëns

0

Myślę, że nie ma opcji wiersza poleceń do tego samego.

Będziesz musiał użyć jvisualvm / jconsole do tego samego.

Raczej zasugerowałbym ci użycie tych narzędzi do identyfikacji, dlaczego twój program ma dużo pamięci.

W każdym razie nie powinieneś wymuszać GC, ponieważ z pewnością zakłóciłoby to algorytm GC i spowolniłoby program.



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.