Comment forcer la collecte des ordures en Java?


Est-il possible de forcer la récupération de place en Java, même si c'est difficile à faire? Je connais System.gc(); et Runtime.gc(); mais ils suggèrent seulement de faire GC. Comment puis-je forcer GC?

Author: Robert Columbia, 2009-09-26

22 answers

Votre meilleure option est d'appeler System.gc() ce qui est simplement une allusion à la garbage collector qui vous souhaitez faire une collection. Il n'y a aucun moyen de forcer et une collecte immédiate car le garbage collector est non déterministe.

 141
Author: Andrew Hare, 2015-07-09 20:47:12

La bibliothèque jlibs a une bonne classe utilitaire pour la collecte des ordures. Vous pouvez forcer la récupération de place en utilisant une petite astuce astucieuse avec des objets WeakReference .

RuntimeUtil.gc () du jlibs:

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }
 49
Author: shams, 2011-08-02 16:19:21

La meilleure façon (sinon seulement) de forcer un GC serait d'écrire une JVM personnalisée. Je crois que les Garbage collectors sont enfichables, vous pouvez donc probablement choisir l'une des implémentations disponibles.

Remarque: Ce n'est PAS la réponse facile.

 39
Author: Mainguy, 2009-09-27 14:07:14

En utilisant le Interface de Machine-outil Virtuelle Java™ (JVM TI), la fonction

jvmtiError ForceGarbageCollection(jvmtiEnv* env)

"Forcera la machine virtuelle à effectuer une récupération de place."La JVM TI fait partie de la Architecture de débogueur de plate-forme JavaTM (JPDA).

 38
Author: trashgod, 2013-01-24 01:45:28

OUI il est presque possible de forcer vous devez appeler des méthodes dans le même ordre et en même temps celles-ci sont:

System.gc ();
System.runFinalization ();

Même si est juste un objet pour nettoyer l'utilisation de ces deux méthodes en même temps forcer le garbage collector à utiliser la méthode finalise() d'objet inaccessible libérant la mémoire assignée et faisant ce que la méthode finalize() indique.

CEPENDANT c'est une pratique terrible d'utiliser le garbage collector car son utilisation pourrait introduire une charge pour le logiciel qui peut être encore pire que sur la mémoire, le garbage collector a son propre thread qui n'est pas possible de contrôler plus selon l'algorithme utilisé par le conseil d'administration pourrait prendre plus de temps et est très inefficace, vous devriez vérifier votre logiciel si pire avec l'aide de la gc car il est certainement cassé, une bonne solution ne doit pas dépendre du gc.

REMARQUE: juste pour garder à l'esprit cela ne fonctionne que si dans la méthode finalize est pas un réaffectation de l'objet, si cela se produit, l'objet restera en vie et aura une résurrection qui est techniquement possible.

 22
Author: legramira, 2017-02-27 00:11:58

Sous la documentation de OutOfMemoryError il déclare qu'il ne sera pas lancé à moins que la machine virtuelle n'ait pas réussi à récupérer de la mémoire après une récupération de place complète. Donc, si vous continuez à allouer de la mémoire jusqu'à ce que vous obteniez l'erreur, vous aurez déjà forcé une récupération de place complète.

Vraisemblablement, la question que vous vouliez vraiment poser était "comment puis-je récupérer la mémoire que je pense que je devrais récupérer par la collecte des ordures?"

 16
Author: Pete Kirkham, 2009-09-26 14:45:46

Pour demander manuellement GC (pas du système.gc ()):

  1. Allez dans : dossier bin dans JDK, par exemple.-C:\Program Fichiers \ Java \ jdk1. 6. 0_31 \ bin
  2. Ouvrir jconsole.exe
  3. Connectez-vous au processus local souhaité.
  4. Allez dans l'onglet Mémoire et cliquez sur Exécuter GC.
 15
Author: Pinkesh Sharma, 2014-01-03 19:38:30

.gc est un candidat pour l'élimination dans les versions futures - un ingénieur Sun a déjà commenté que peut-être moins de vingt personnes dans le monde savent réellement comment utiliser .gc ()-J'ai travaillé la nuit dernière pendant quelques heures sur une structure de données centrale / critique utilisant des données générées par SecureRandom, à quelque part juste après 40 000 objets, la machine virtuelle ralentirait comme si elle était à court de pointeurs. De toute évidence, il étouffait sur les tables de pointeur 16 bits et présentait des "machines défaillantes" classiques" comportement.

J'ai essayé -Xms et ainsi de suite, gardé peu tourner jusqu'à environ 57,xxx quelque chose. Ensuite, il fonctionnerait gc passant de disons 57,127 à 57,128 après un gc ()-à peu près au rythme du code-ballonnement au camp Easy Money.

Votre conception a besoin d'un remaniement fondamental, probablement une approche de fenêtre coulissante.

 11
Author: Nicholas Jordan, 2009-09-26 17:30:59

La spécification JVM ne dit rien de spécifique à propos de la récupération de place. Pour cette raison, les fournisseurs sont libres de mettre en œuvre le GC à leur manière.

Donc, cette imprécision provoque une incertitude dans le comportement de récupération de place. Vous devez vérifier les détails de votre JVM pour connaître les approches/algorithmes de garbage collection. Il existe également des options pour personnaliser le comportement.

 6
Author: rai.skumar, 2014-08-20 11:49:45

Utile pour batch / crontab:

Jdk1.7.0/bin/jcmd GC.exécuter

Voir :

 6
Author: guest, 2018-07-17 12:41:18

Si vous devez forcer la récupération de place, vous devriez peut-être considérer comment vous gérez les ressources. Créez-vous de grands objets qui persistent en mémoire? Créez-vous de gros objets (par exemple, des classes graphiques) qui ont une interface Disposable et n'appellent pas dispose() une fois cela fait? Déclarez-vous quelque chose au niveau de la classe dont vous n'avez besoin que dans une seule méthode?

 4
Author: Bob Kaufman, 2009-09-26 13:33:46

Il serait préférable que vous décriviez la raison pour laquelle vous avez besoin de la collecte des ordures. Si vous utilisez SWT, vous pouvez disposer de ressources telles que Image et Font pour libérer de la mémoire. Par exemple:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

Il existe également des outils pour déterminer les ressources non divulguées.

 2
Author: Paul Lammertsma, 2009-09-26 13:25:18

Utilisez Runtime.getRuntime().gc() ou utilisez la méthode utilitaire System.gc()

 1
Author: nabster, 2018-02-06 04:22:05

Vraiment, je ne vous comprends pas. Mais pour être clair sur la " Création d'objets Infinis" Je voulais dire qu'il y a un morceau de code à mon grand système faire la création de objets qui manipule et vivant dans mémoire, je ne pouvais pas obtenir ce morceau de code en fait, juste un geste!!

C'est correct, seul geste. Vous avez à peu près les réponses standard déjà données par plusieurs affiches. Prenons ceci un par un:

  1. je ne pouvais pas obtenir ce morceau de code en fait

Correcte, il n'y a pas de jvm - telle n'est qu'une spécification, un tas d'informatique décrivant un comportement désiré ... J'ai récemment creusé dans l'initialisation d'objets Java à partir de code natif. Pour obtenir ce que vous voulez, la seule façon est de faire ce qu'on appelle l'annulation agressive. Les erreurs si elles sont mal faites sont si mauvaises que si elles sont mal faites, nous devons nous limiter à la portée initiale de la question:

  1. un morceau de code sur mon grand système faire création d'objets

La plupart des affiches ici supposeront que vous dites que vous travaillez à une interface, si tel nous devrions voir si vous êtes remis l'objet entier ou un élément à la fois.

Si vous n'avez plus besoin d'un objet, vous pouvez affecter null à l'objet mais si vous vous trompez, une exception de pointeur null est générée. Je parie que vous pouvez obtenir un meilleur travail si vous utilisez NIO

Chaque fois que vous ou moi ou quelqu'un d'autre obtient: " S'il vous plait, j'en ai besoin horriblement." c'est un précurseur presque universel de la destruction quasi totale de ce sur quoi vous essayez de travailler .... écrivez - nous un petit exemple de code, en désinfectant tout code utilisé et montrez-nous votre question.

Ne soyez pas frustré. Souvent, ce que cela résout, c'est que votre dba utilise un package acheté quelque part et que la conception originale n'est pas modifiée pour les structures de données massives.

C'est très courant.

 0
Author: Nicholas Jordan, 2009-10-02 05:17:05

Si vous manquez de mémoire et que vous obtenez un OutOfMemoryException, vous pouvez essayer d'augmenter la quantité d'espace de tas disponible pour java en démarrant votre programme avec java -Xms128m -Xmx512m au lieu de simplement java. Cela vous donnera une taille de tas initiale de 128 Mo et un maximum de 512 Mo, ce qui est beaucoup plus que les 32 Mo/128 Mo standard.

 0
Author: Viktor Dahl, 2011-03-09 16:24:23

(Désolé, je ne peux pas ajouter cela comme commentaire car je n'ai pas assez de points de réputation.)

J'ai interviewé une fois dans une entreprise de traitement d'images pour un travail Java (même si je n'avais pas beaucoup d'expérience java.)

Leur histoire de malheur qui était intéressant pour moi, était leur programme allouer un ÉNORME tampon pour l'image. Une fois qu'ils en avaient fini avec l'image et la mémoire, ils la déféraient. Sachant qu'ils avaient vraiment besoin de récupérer la mémoire plus tôt que tard, ils ont essayé d'utiliser un appel explicite à Java gc () pendant une période de silence du programme. Malheureusement, gc () n'est qu'une suggestion au runtime Java et n'a eu aucun effet.

Si je me souviens bien, ils ont fini par devoir recycler la mémoire eux-mêmes.

 0
Author: Clem Wang, 2016-12-08 23:36:29

Une autre option consiste à ne pas créer de nouveaux objets.

Le pool d'objets est absent pour réduire le besoin de GC en Java.

La mise en commun d'objets ne sera généralement pas plus rapide que la création d'objets (en particulier pour les objets légers) mais elle est plus rapide que la récupération de place. Si vous avez créé 10 000 objets et que chaque objet était de 16 octets. C'est 160 000 octets que GC doit récupérer. D'autre part, si vous n'avez pas besoin de tous les 10 000 en même temps, vous pouvez créer un pool pour recycler/réutiliser le objets qui élimine le besoin de construire de nouveaux objets et élimine le besoin de GC anciens objets.

Quelque chose comme ça (non testé). Et si vous voulez qu'il soit sécurisé, vous pouvez échanger la LinkedList contre un ConcurrentLinkedQueue.

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}
 0
Author: Aaron T Harris, 2018-09-26 07:04:15

POUR info

Le système d'appel de méthode.runFinalizersOnExit (true) garantit que les méthodes finalizer sont appelés avant l'arrêt de Java. Cependant, cette méthode est intrinsèquement dangereuse et est obsolète. Une alternative consiste à ajouter des "crochets d'arrêt" avec la méthode Runtime.addShutdownHook.

Masarrat Siddiqui

 -1
Author: Masarrat Siddiqui, 2013-01-07 07:11:43

Il existe un moyen indirect de forcer garbage collector. Vous avez juste besoin de remplir le tas avec des objets temporaires jusqu'au moment où le garbage collector s'exécutera. J'ai fait une classe qui force le garbage collector de cette façon:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

Utilisation:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

Je ne sais pas à quel point cette méthode est utile, car elle remplit constamment le tas, mais si vous avez une application critique qui DOIT forcer GC - alors que cela peut être le moyen portable Java de forcer GC.

 -1
Author: Agnius Vasiliauskas, 2014-10-22 12:47:18

Je voudrais ajouter quelque chose ici. Veuillez ne pas que Java s'exécute sur une machine virtuelle et non sur une machine réelle. La machine virtuelle a son propre moyen de communication avec la machine. Il peut varry à partir d'un système à l'autre. Maintenant, lorsque nous appelons le GC, nous demandons à la Machine virtuelle de Java d'appeler le Garbage Collector.

Puisque le Garbage Collector est avec la machine virtuelle , nous ne pouvons pas le forcer à faire un nettoyage là-bas et ensuite. Plutôt que nous mettons notre demande en file d'attente avec le Garbage Collector. Il dépend de la machine virtuelle, après un temps particulier (cela peut changer d'un système à l'autre, généralement lorsque la mémoire seuil allouée à la JVM est pleine), la machine réelle libérera de l'espace. : D

 -1
Author: Saubhagya Ranjan Das, 2015-09-04 03:49:00

Le code suivant est tiré de l'assertGC (...) méthode. Il essaie de forcer le garbage collector non déterministe à collecter.

   List<byte[]> alloc = new ArrayList<byte[]>();
   int size = 100000;
   for (int i = 0; i < 50; i++) {
        if (ref.get() == null) {
             // Test succeeded! Week referenced object has been cleared by gc.
             return;
        }
        try {
             System.gc();
        } catch (OutOfMemoryError error) {
             // OK
        }
        try {
             System.runFinalization();
        } catch (OutOfMemoryError error) {
             // OK
        }

        // Approach the jvm maximal allocatable memory threshold
        try {
             // Allocates memory.
             alloc.add(new byte[size]);

             // The amount of allocated memory is increased for the next iteration.
             size = (int)(((double)size) * 1.3);
        } catch (OutOfMemoryError error) {
             // The amount of allocated memory is decreased for the next iteration.
             size = size / 2;
        }

        try {
             if (i % 3 == 0) Thread.sleep(321);
        } catch (InterruptedException t) {
             // ignore
        }
   }

   // Test failed! 

   // Free resources required for testing
   alloc = null;

   // Try to find out who holds the reference.
   String str = null;
   try {
        str = findRefsFromRoot(ref.get(), rootsHint);
   } catch (Exception e) {
        throw new AssertionFailedErrorException(e);
   } catch (OutOfMemoryError err) {
        // OK
   }
   fail(text + ":\n" + str);

Source (j'ai ajouté quelques commentaires pour plus de clarté): Exemple NbTestCase

 -1
Author: H. Hess, 2017-08-04 09:49:57

La meilleure façon (sinon seulement) de forcer un GC serait d'écrire un JVM personnalisé. Je crois que les Garbage collectors sont enfichables, vous pouvez donc probablement choisir l'une des implémentations disponibles.

 -3
Author: geeta, 2013-03-21 06:34:03