Как заставить сборку мусора из оболочки?


107

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

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

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

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


Не то же самое, что stackoverflow.com/questions/1481178/…
— Raedwald

Ответы:


25

Вы можете сделать это с помощью бесплатной программы jmxterm .

Запустите его так:

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

Оттуда вы можете подключиться к хосту и запустить сборщик мусора:

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

ОБНОВЛЕНИЕ: здесь однострочник с использованием jmxterm:

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

347

Начиная с 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>, это вызовет полный сбор мусора в куче, прежде чем он что-либо распечатает.


3
принудительно выполнить сборку мусора на всех javas: ps axf | grep java | grep -v grep | awk '{print "jmap -histo: live" $ 1}' | sh
— gtrak

1
Где это задокументировано? А как насчет без: live (например, когда нужен -F)?
— nafg

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
— dhockey 09

Я еще не сталкивался с этим сообщением об ошибке. Может сработает sudo -u <process_owner> jcmd <pid> GC.run, не могли бы вы попробовать? Командование должно быть безопасным
— Томас Ребеле

Я хотел бы, но у меня нет доступа к sudo на этой машине.
— dhockey

Инструмент работает правильно. У вас просто нет необходимых разрешений в операционной системе для его выполнения. То же самое и с другими приложениями, даже не использующими Java.
— Aled 03

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.

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

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


0

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

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

-10

просто:

kill -SIGQUIT <PID>

4
Это вызовет дамп кучи, а не сборку мусора
— Дрор Березницкий

по крайней мере, Solaris делает GC Force.
— Амин Аббаспур,

2
Даже в Solaris SIGQUIT не запускает ни сборщик мусора, ни дамп кучи. SIGQUIT вызовет дамп потока только для HotSpot. Для IBM JVM это настраивается.
— Мирча Вутцовичи

Не запускает GC, просто распечатайте трассировку стека.
— Элад Табак
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.