Как вы принудительно собираете мусор из Shell?

Итак, я смотрю кучу с jmap на удаленной коробке, и я хочу заставить сбор мусора на ней. Как вы это делаете, не вставляя jvisualvm или jconsole и друзей?

Я знаю, что вы не должны практиковать принуждение к сбору мусора - вам нужно просто понять, почему куча большая/растет.

Я также понимаю, что System.GC() фактически не заставляет сбор мусора - он просто сообщает GC, что вы хотите, чтобы он произошел.

Сказав, что есть способ сделать это легко? Некоторое приложение командной строки мне не хватает?

Ответ 1

Вы можете сделать это через бесплатную программу 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 ​​/other. Я использовал 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

Ответ 2

Начиная с JDK 7 вы можете использовать JDK-команду "jcmd", например:

jcmd <pid> GC.run

Ответ 3

Если вы запустите jmap -histo:live <pid>, это заставит полный GC в куче, прежде чем он что-либо напечатает.

Ответ 4

Дополнение к 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
...

Эту проблему можно решить с помощью ответа на этот стекопоток

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

где <process_owner> - это пользователь, который запускает процесс с PID <pid>. Вы можете получить оба из top или htop

Ответ 5

Есть еще несколько решений (здесь уже много хороших):

  • Напишите небольшой код для доступа к 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

Это хорошо, потому что это только одна строка, и вы можете легко разместить ее в script.

Ответ 6

Я не думаю, что для этого есть какая-либо опция командной строки.

Вам нужно будет использовать jvisualvm/jconsole для этого.

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

В любом случае вы не должны принуждать GC, так как это, безусловно, нарушит алгоритм GC и сделает вашу программу медленной.

Ответ 7

Если вы используете jolokia с вашим приложением, вы можете запустить сборку мусора с помощью этой команды:

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

Ответ 8

для Linux:

$ jcmd $(pgrep java) GC.run

jcmd упакован с JDK, $(pgrep java) получает идентификатор процесса Java

Ответ 9

только

kill -SIGQUIT <PID>