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


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.