Quand le système.gc () faire n'importe quoi

je sais que la collecte des ordures est automatisée en Java. Mais j'ai compris que si vous écrivez System.gc() dans votre code, la VM Java peut décider ou non à l'exécution de faire une collecte des ordures à ce moment-là. Comment cela fonctionne précisément? Sur quelle base/paramètres la VM décide-t-elle de faire (ou de ne pas faire) un CG lorsqu'elle voit un System.gc() ? Y a-t-il des exemples dans lesquels est une bonne idée de mettre ceci dans votre code?

103
demandé sur Raedwald 2008-09-16 00:20:17

17 réponses

dans la pratique, il généralement décide de faire une collecte des ordures. La réponse varie en fonction de beaucoup de facteurs, comme le JVM que vous utilisez, le mode dans lequel il est, et l'algorithme de collecte des ordures qu'il utilise.

Je ne m'en remettrais pas à votre code. Si le JVM est sur le point de lancer un système D'appel OutOfMemoryError.gc() ne sont pas l'arrêter, parce que le garbage collector va tenter de libérer autant qu'il le peut avant que extrême. La seule fois où je l'ai vu utilisé dans la pratique est dans IDEs où il est attaché à un bouton qu'un utilisateur peut cliquer, mais même là, il n'est pas très utile.

53
répondu jodonnell 2008-09-15 20:23:41

le seul exemple qui me vient à l'esprit est celui de L'endroit où il est logique d'appeler système.gc () est en train de profiler une application pour rechercher des fuites de mémoire possibles. Je crois que les profileurs appellent cette méthode juste avant de prendre un instantané de mémoire.

28
répondu Guillermo Vasconcelos 2008-09-15 20:36:59

vous n'avez aucun contrôle sur GC en java -- la VM décide. Je n'ai jamais rencontré un cas où System.gc() est nécessaire . Comme un appel System.gc() suggère simplement que la VM fait une collecte des ordures et qu'elle fait aussi une collecte complète des ordures (anciennes et nouvelles générations dans un tas multi-générationnel), alors il peut réellement causer plus cycles cpu à consommer que nécessaire.

dans certains cas, il peut être logique de suggérez à la VM qu'il faire une collecte complète maintenant que vous savez peut-être que l'application sera assis inactif pour les prochaines minutes avant que le levage lourd se produit. Par exemple, juste après l'initialisation d'un grand nombre d'objets temporaires pendant le démarrage de l'application (i.e., j'ai juste mis en cache une tonne d'information, et je sais que je n'aurai pas beaucoup d'activité pendant une minute ou deux). Pensez à un IDE comme eclipse de départ, il fait beaucoup pour initialiser, donc peut-être immédiatement après l'initialisation, il est logique de faites une gc complète à ce point.

23
répondu DustinB 2015-08-26 12:44:39

la spécification Java Language ne garantit pas que la JVM lancera un CG lorsque vous appelez System.gc() . C'est la raison de ce "peut ou ne peut pas décider de faire un GC à ce point".

maintenant, si vous regardez code source OpenJDK , qui est l'épine dorsale D'Oracle JVM, vous verrez qu'un appel à System.gc() ne démarre un cycle GC. Si vous utilisez une autre JVM, comme J9, vous devez vérifier sa documentation pour trouver la réponse. Pour par exemple, le JVM D'Azul a un collecteur d'ordures qui fonctionne en continu, donc un appel à System.gc() ne fera rien

une autre réponse mentionne le démarrage D'un CG dans JConsole ou VisualVM. Fondamentalement, ces outils font appel à distance System.gc() .

en général, vous ne voulez pas démarrer un cycle de collecte des ordures à partir de votre code, car il gâche la sémantique de votre application. Votre application fait du business, la JVM prend soin de la mémoire gestion. Vous devez garder ces préoccupations séparées (ne pas faire votre application faire de la gestion de la mémoire, se concentrer sur les affaires).

cependant, il y a peu de cas où un appel à System.gc() pourrait être compréhensible. Prenons, par exemple, les microbenchmarks. Personne ne veut qu'un cycle GC se produise au milieu d'un microbenchmark. Vous pouvez donc déclencher un cycle GC entre chaque mesure pour vous assurer que chaque mesure commence par un tas vide.

19
répondu Pierre Laporte 2013-05-11 10:55:34

Vous devez être très prudent si vous appelez System.gc() . L'appeler peut ajouter des problèmes de performances inutiles à votre application, et il n'est pas garanti d'effectuer effectivement une collecte. Il est en fait possible de désactiver explicitement System.gc() via l'argument java -XX:+DisableExplicitGC .

je recommande vivement de lire les documents disponibles à Java HotSpot Garbage Collection pour plus de détails sur la collecte des ordures.

17
répondu David Schlosnagle 2014-12-09 14:20:39

System.gc() est mis en œuvre par la VM, et ce qu'elle fait est spécifique à la mise en œuvre. L'exécuteur pourrait simplement revenir et ne rien faire, par exemple.

quand un manuel de recueillir, le seul moment où vous voulez le faire est lorsque vous abandonner une grande collection contenant des charges de petites collections-- Map<String,<LinkedList>> par exemple--et vous voulez essayer de prendre le coup de perf alors et là, mais pour la plupart, vous ne devriez pas vous inquiéter à ce sujet. Le GC sait mieux que vous--malheureusement--la plupart du temps.

10
répondu Patrick 2015-08-26 12:54:08

si vous utilisez des tampons de mémoire directe, la JVM n'exécute pas le GC pour vous, même si vous êtes à court de mémoire directe.

si vous appelez ByteBuffer.allocateDirect() et que vous obtenez un OutOfMemoryError, vous pouvez trouver que cet appel est bon après avoir déclenché un CG manuellement.

8
répondu Peter Lawrey 2012-12-13 01:53:53

la plupart des JVM déclencheront une GC (en fonction de l'interrupteur courant-XX:DiableExplicitGC et-XX:+Explicitgcinvokesconcurrence). Mais la spécification est tout simplement moins bien définie afin de permettre de meilleures implémentations plus tard.

la spécification doit être clarifiée: bogue n ° 6668279: système (spec).gc () devrait indiquer que nous ne recommandons pas l'utilisation et ne garantissons pas le comportement

à l'interne, la méthode gc est utilisée par le RMI et le NIO, et ils nécessitent une exécution synchrone, qui est actuellement en discussion:

Bogue N ° 5025281: Autoriser Le Système.gc() pour déclencher simultanées (non stop-le-monde) complète les collections

3
répondu eckes 2014-10-13 23:05:24

nous ne pouvons jamais forcer la collecte des ordures. Système.gc suggère seulement vm pour la collecte des ordures, cependant, vraiment à quelle heure le mécanisme fonctionne, personne ne sait, c'est comme indiqué par les spécifications JSR.

2
répondu lwpro2 2010-10-31 03:53:53

il y a beaucoup à dire en prenant le temps de tester les différents paramètres de collecte des ordures, mais comme il a été mentionné ci-dessus, il n'est généralement pas utile de le faire.

je travaille actuellement sur un projet impliquant un environnement limité en mémoire et une quantité relativement importante de données--il y a quelques gros morceaux de données qui poussent mon environnement à sa limite, et même si j'ai pu faire baisser l'utilisation de la mémoire afin qu'en théorie ça devrait fonctionner très bien, je voudrais encore obtenir des erreurs d'espace tas - - - les options verbeuses GC m'ont montré qu'il essayait de ramasser les ordures, mais en vain. Dans le débogueur, je pourrais exécuter le système.gc() et bien sûr qu'il y aurait "beaucoup" de mémoire disponible...pas beaucoup de supplément, mais assez.

par conséquent, la seule fois où mon application appelle le système.gc() est quand il est sur le point d'entrer le segment de code où les gros tampons nécessaires au traitement des données seront alloués, et un test sur la mémoire libre disponible indique que je ne suis pas garanti de l'avoir. En particulier, je regarde un environnement de 1 Go où au moins 300 Mo est occupé par des données statiques, avec la plupart des données non statiques étant liés à l'exécution-sauf quand les données traitées se trouve être au moins 100-200 Mo à la source. Cela fait partie d'un processus de conversion automatique des données, de sorte que toutes les données existent pour des périodes relativement courtes à long terme.

malheureusement, alors que l'information en ce qui concerne les différentes options de réglage du collecteur d'ordures est disponible, il semble en grande partie un processus expérimental et les spécifications de niveau inférieur nécessaires pour comprendre comment gérer ces situations spécifiques ne sont pas facilement obtenus.

tout cela étant dit, même si j'utilise le système.gc (), j'ai quand même continué à utiliser les paramètres de ligne de commande et j'ai réussi à améliorer le temps de traitement global de ma demande d'un montant relativement important, en dépit d'être incapable de surmonter la pierre d'achoppement posée par le fait de travailler avec les grands blocs de données. Cela étant dit, le Système.gc() est un outil....un outil très peu fiable, et si vous n'êtes pas prudent avec la façon dont vous l'utilisez, vous souhaiterez qu'il n'a pas fonctionné plus souvent qu'autrement.

2
répondu Kyune 2011-03-07 09:00:13

Je ne peux pas penser à un exemple précis quand il est bon d'exécuter la commande CG explicite.

en général, l'exécution d'un CG explicite peut en fait causer plus de tort que de bien, parce qu'un CG explicite déclenchera une collection complète, ce qui prend beaucoup plus de temps à parcourir chaque objet. Si ce CG explicite finit par être appelé à plusieurs reprises, il pourrait facilement conduire à une application lente car beaucoup de temps est passé à exécuter des GCs complets.

alternativement si on va sur le tas avec un analyseur de tas et vous soupçonnez qu'un composant de bibliothèque appelle des GC explicites, Vous pouvez l'éteindre en ajoutant: gc=-XX:+Disablexplicitgc aux paramètres JVM.

1
répondu zxcv 2008-09-15 20:32:20

normalement, la VM ferait une collecte de déchets automatiquement avant de lancer une OutOfMemoryException, donc l'ajout d'un appel explicite ne devrait pas aider, sauf qu'il déplace peut-être la performance frappé à un moment plus tôt dans le temps.

cependant, je pense que j'ai rencontré un cas où il pourrait être pertinent. Je ne suis pas sûr, car je dois encore tester si elle a un effet:

quand vous vous souvenez-map un fichier, je crois que l'appel map() lance un IOException quand un bloc de mémoire assez grand n'est pas disponible. Une collecte des ordures juste avant le fichier map () pourrait aider à prévenir cela, je pense. Qu'en pensez-vous?

1
répondu 2009-02-10 13:20:10

en bref:

Les paramètres

dépendent de la VM.

exemple d'Utilisation - Je ne peux pas penser à un pour l'exécution / applications de production, mais il est utile de l'Exécuter pour certains harnais de profilage, comme l'appel

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();
1
répondu mataal 2011-08-02 05:40:03

si vous voulez savoir si votre System.gc() est appelé, Vous pouvez avec le nouveau Java 7 update 4 obtenir notification lorsque le JVM effectue la collecte des ordures.

Je ne suis pas sûr à 100% que la classe GarbageCollectorMXBean a été introduite dans Java 7 update 4 cependant, parce que je n'ai pas pu le trouver dans les notes de version, mais j'ai trouvé l'information dans le javaperformancetuning .site com

1
répondu Shervin Asgari 2012-07-25 12:07:09

Accroding à Penser en Java par Bruce Eckel, un cas d'utilisation explicite du Système.gc () appel est quand vous voulez forcer la finalisation, c.-à-d. l'appel à finalisation méthode.

0
répondu Asterisk 2011-09-21 04:44:57

tout système.gc fonctionne,il va arrêter le monde:tous les répondants sont arrêtés afin que collecteur d'ordures peut scanner chaque objet pour vérifier si elle est nécessaire supprimé. si l'application est un projet web, toutes les demandes sont arrêtées jusqu'à ce que gc termine,et cela entraînera votre projet web ne peut pas fonctionner dans un monent.

0
répondu fleture 2012-07-06 09:57:38

Garbage Collection est bon dans Java , si nous exécutons un logiciel codé en java dans un ordinateur de bureau/Ordinateur Portable/serveur. Vous pouvez appeler System.gc() ou Runtime.getRuntime().gc() dans Java .

notez juste qu'aucun de ces appels n'est garanti pour faire quoi que ce soit. Ils ne sont qu'une suggestion pour le jvm de diriger le collecteur d'ordures. C'est à la JVM de décider si elle gère le GC ou non. Donc, réponse courte: nous ne savons pas quand il fonctionne. Réponse plus longue: JVM lancerait gc si elle a le temps que.

je crois, la même chose s'applique pour Android. Cependant, cela pourrait ralentir votre système.

0
répondu Naveen 2017-10-02 07:48:55