web-dev-qa-db-fra.com

Comment forcer le ramassage des ordures à partir de Shell?

Donc, je regarde un tas avec jmap sur une boîte distante et je veux forcer le ramassage des ordures dessus. Comment faites-vous cela sans tomber dans jvisualvm ou jconsole and friends?

Je sais que vous ne devriez pas forcer la récupération des ordures - vous devez juste comprendre pourquoi le tas est gros/en croissance.

Je réalise également que System.GC () ne force pas la récupération de place, il indique simplement au GC que vous souhaitez que cela se produise.

Cela dit, y a-t-il un moyen de le faire facilement? Une application en ligne de commande me manque?

85
eyberg

Vous pouvez le faire via le programme gratuit jmxterm .

Allumez-le comme ça:

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

À partir de là, vous pouvez vous connecter à un hôte et déclencher le 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

Consultez la documentation sur le site Web de jmxterm pour plus d'informations sur l'intégration de cela dans bash/Perl/Ruby/d'autres scripts. Pour ce faire, j'ai utilisé popen2 en Python ou open3 en Perl.

UPDATE: voici un one-liner utilisant jmxterm:

echo run -b Java.lang:type=Memory gc | Java -jar jmxterm-1.0-alpha-4-uber.jar -n -l Host:port
21
Harold L

Depuis JDK 7, vous pouvez utiliser l'outil de commande JDK 'jcmd' tel que:

jcmd <pid> GC.run

279
user3198490

Si vous exécutez jmap -histo:live <pid>, cela forcera un GC complet sur le tas avant qu'il n'imprime quoi que ce soit.

98
Will Hartung

Ajout à la réponse de user3198490 . L'exécution de cette commande peut vous donner le message d'erreur suivant:

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

Ceci peut être résolu avec l'aide de cette réponse stackoverflow

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

<process_owner> est l'utilisateur qui exécute le processus avec le PID <pid>. Vous pouvez obtenir les deux à partir de top ou htop

10
Thomas Rebele

Il y a quelques autres solutions (beaucoup de bonnes ici déjà):

  • Ecrivez un petit code pour accéder au MemoryMBean et appelez gc().
  • A l'aide d'un client JMX en ligne de commande (tel que cmdline-jmxclient , jxmterm ) et exécutez l'opération gc() sur le MemoryMBean

L'exemple suivant concerne le cmdline-jmxclient:

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

C'est bien parce que ce n'est qu'une ligne et que vous pouvez le mettre très facilement dans un script.

6
The Alchemist

Je ne pense pas qu'il existe une option de ligne de commande pour les mêmes.

Vous devrez utiliser jvisualvm/jconsole pour la même chose.

Je vous suggérerais plutôt d’utiliser ces outils pour identifier, pourquoi votre programme a beaucoup de mémoire.

Quoi qu'il en soit, vous ne devriez pas forcer GC, cela perturberait certainement son algorithme et ralentirait votre programme.

0
YoK

Si vous utilisez jolokia avec votre application, vous pouvez déclencher un garbage collection avec cette commande:

curl http://localhost:8558/jolokia/exec/Java.lang:type=Memory/gc
0
dustmachine