Як змусити збирати сміття зі шкаралупи?


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 ​​/ інші. Для цього я використовував popen2 в Python або open3 в Perl.

ОНОВЛЕННЯ: ось одне вкладиш за допомогою 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.
Алі Салех

104

Якщо ви запустите jmap -histo:live <pid>, це змусить повний GC на купі, перш ніж він щось роздрукує.


3
примушуйте збирати сміття на всіх javas: ps axf | grep java | grep -v grep | awk '{print "jmap -histo: live" $ 1}' | sh
gtrak

1
Де це задокументовано? А як же без: жити (наприклад, коли потрібен -F)?
нафг

7
Привіт з таємничим майбутнім 2014 року jcmd- тепер правильний інструмент для роботи.
noahlz

16

Доповнення до user3198490 відповіді «s. Запуск цієї команди може дати вам таке повідомлення про помилку:

$ 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
докей

Я ще не стикався з цим повідомленням про помилку. Може, це спрацьовує sudo -u <process_owner> jcmd <pid> GC.run, ви можете спробувати? Команда повинна бути безпечною
Томас Ребеле

Я мав би, але у мене немає доступу до судо на цій машині.
докей

Інструмент працює правильно. Ви просто не маєте прав дозволу в операційній системі для його виконання. Те саме стосується інших програм, навіть не використовуючи Java.
aled

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)отримує ідентифікатор процесу java


Це працюватиме лише тоді, коли працює один Java-процес. В іншому випадку він буде інтерпретувати другий PID як команду для jcmd, яка, очевидно, не розпізнається, і видасть помилку.
Cas Eliëns

0

Я не думаю, що для цього немає варіанту командного рядка.

Вам потрібно буде використовувати jvisualvm / jconsole для того ж.

Я б скоріше запропонував би вам використовувати ці інструменти для ідентичності, чому ваша програма має велику пам’ять.

У будь-якому разі не варто змушувати GC, оскільки це, безумовно, порушить алгоритм GC та зробить вашу програму повільною.


0

Якщо ви використовуєте jolokia у своїй програмі, ви можете запустити збір сміття за допомогою цієї команди:

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

-10

просто:

kill -SIGQUIT <PID>

4
Це спровокує збирання сміття, а не сміття
Дрор Березницький

принаймні, це сонячна енергія, це робить силу GC.
Амін Аббаспур

2
Навіть у Solaris SIGQUIT не спричинить ані GC, ані купи купи. SIGQUIT запустить дамп потоку тільки для HotSpot. Для IBM JVM він налаштовується.
Мірча Вутковичі

Не запустить GC, просто надрукуйте слід стека.
Елад Табак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.