Java garbage collector-Quand collecte-t-il?


Qu'est-ce qui détermine quand le garbage collector collecte réellement? Il arrive après un certain temps ou après une certaine quantité de mémoire ont été utilisés? Ou existe-il d'autres facteurs?

Author: nalo, 2009-10-17

6 answers

Il s'exécute lorsqu'il détermine qu'il est temps de s'exécuter. Une stratégie courante dans les garbage collectors générationnels consiste à exécuter le collecteur lorsqu'une allocation de mémoire generation-0 échoue. Autrement dit, chaque fois que vous allouez un petit bloc de mémoire (les gros blocs sont généralement placés directement dans les générations "plus anciennes"), le système vérifie s'il y a suffisamment d'espace libre dans le tas gen-0, et s'il n'y en a pas, il exécute le GC pour libérer de l'espace pour que l'allocation réussisse. Les anciennes données sont ensuite déplacées vers le tas gen-1, et quand l'espace s'épuise, le GC exécute une collection à ce sujet, mettant à niveau les données qui ont été là le plus longtemps vers le tas gen-2, et ainsi de suite. Donc, le GC ne se contente pas de"courir". Il peut fonctionner uniquement sur le tas gen-0 (et la plupart des collections le feront), ou il peut vérifier chaque génération si elle doit vraiment libérer beaucoup de mémoire (ce qui n'est nécessaire que rarement).

, Mais c'est loin de la seulement stratégie. Un GC concurrent s'exécute en arrière-plan, nettoyant alors que le programme est en cours d'exécution. Certains GC peuvent s'exécuter dans le cadre de chaque allocation de mémoire. Un collecteur incrémental peut le faire, en scannant quelques objets à chaque allocation de mémoire.

Le point entier dans un garbage collector est qu'il devrait juste faire sa chose sans nécessiter aucune entrée de l'utilisateur. Donc, en général, vous ne pouvez pas, et ne devriez pas, prédire quand il fonctionnera.

Je crois que Suns JVM a gagné un GC générationnel il n'y a pas si longtemps (v1.6 peut-être? Je n'ai pas codé Java depuis des lustres, donc je ne sais pas à ce sujet, mais je me souviens avoir été surpris il n'y a pas si longtemps, lorsque l'un des arguments de vente de la nouvelle version était "un GC générationnel". Notamment parce que. NET en a un depuis le jour 1.)

Les autres JVM sont bien sûr libres de choisir la stratégie qu'ils aiment.

EDIT: La partie ci-dessus sur Java et generational GC n'est pas vraie. Voir ci-dessous pour plus de détails:

Les machines virtuelles 1.0 et 1.1 utilisaient un collecteur de balayage de marques, qui pouvait fragmenter le tas après une collecte des ordures. À partir de Java 1.2, les Machines virtuelles sont passées à un collecteur générationnel, qui a un bien meilleur comportement de défragmentation (voir Java theory and practice: Garbage collection and performance).

Donc Java a en fait un GC générationnel depuis des lustres. Quoi de neuf dans Java 6 est le Garbage-First Garbage collector (G1) qui est disponible dans Java 6u14. Selon l'article revendiquant la libération en 1.6.0_14: Il n'est pas activé par défaut. Le collecteur parallèle est toujours le GC par défaut et est le GC le plus efficace pour un usage domestique commun. G1 est censé être une alternative pour le collecteur concurrent. Il est conçu pour être plus prévisible et permettre une allocation rapide avec la conception de régions de mémoire.

 26
Author: jalf, 2009-10-17 18:46:09
  • Cela dépend de la manière dont le programme JIT a été compilé.
  • De l'extérieur, nous ne pouvons pas vraiment dire quand il fonctionnera.
  • Il suit un algorithme qui dépend de ce GC particulier.
  • La machine virtuelle Java s'exécute sur la machine cliente avec une certaine mémoire virtuelle en cas de défaut de Windows est de 4 Go. Cela dépend également de cette mémoire virtuelle libre à ce moment précis.

Vous pouvez essayer ce petit programme pour vérifier le comportement de GC

public class GCTest {

   final int NELEMS = 50000;

   void eatMemory() {

      int[] intArray = new int[NELEMS];

      for (int i=0; i<NELEMS; i++) {
        intArray[i] = i;
      }

   }

   public static void main (String[] args) {

      GCTest gct = new GCTest();

      // Step 1: get a Runtime object
      Runtime r = Runtime.getRuntime();

      // Step 2: determine the current amount of free memory
      long freeMem = r.freeMemory();
      System.out.println("free memory before creating array: " + freeMem);

      // Step 3: consume some memory
      gct.eatMemory();

      // Step 4: determine amount of memory left after consumption
      freeMem = r.freeMemory();
      System.out.println("free memory after creating array:  " + freeMem);

      // Step 5: run the garbage collector, then check freeMemory
      r.gc();
      freeMem = r.freeMemory();
      System.out.println("free memory after running gc():    " + freeMem);
   }
}

Sortie possible May Mai être différent dans votre cas,

free memory before creating array: 4054912
free memory after creating array:  3852496
free memory after running gc():    4064184

Vérifier ce lien http://www.devdaily.com/java/edu/pj/pj010008/

 7
Author: Xinus, 2009-10-17 13:45:32

Cela dépend beaucoup du garbage collector que vous utilisez réellement, de la façon dont il est réglé et de beaucoup d'entrées.

Pour une descente du Garbage Collector HotSpot (le plus commun qui vient avec Java) et comment il est réglé, vous pouvez consulter ce lien

 5
Author: tschaible, 2009-10-17 13:33:30

Cela dépend complètement de la JVM réelle et de ce qu'elle choisit de faire, et est fondamentalement hors de vos mains en tant que programmeur. Les experts die-hard Greybearded peuvent vouloir dire à la JVM qu'ils connaissent mieux, mais pour les simples mortels, cela devrait être considéré comme de la magie noire mieux laissée seule.

Ce qui devrait vous préoccuper, c'est s'il peut suivre le taux de création et d'élimination des objets par vos programmes. Sinon, votre programme entier est arrêté pendant le nettoyage global. Que il s'avère que les temps de réponse sont très mauvais, mais cela arrive rarement pour les JVM modernes sur les ordinateurs modernes.

Si vous êtes curieux de savoir ce qui se passe dans votre programme et quand, alors étudiez l'outil "jvisualvm" dans les versions récentes du JDK Java 6. Il est vraiment idéal pour jeter un oeil à l'intérieur.

 2
Author: Thorbjørn Ravn Andersen, 2009-10-17 17:23:37

Le garbage collector s'exécute quand il a besoin de ressources et sur une base régulière que vous pouvez influencer en disant quand est un bon moment pour passer CPU sur la collecte, en utilisant Système.gc()

Vous pouvez aider le garbage collector en annulant explicitement les références, par exemple en donnant à vos objets init() des méthodes qui allouent des ressources et cleanup() des méthodes qui nettoient explicitement ces ressources et annulent leurs références. En annulant les références vous même vous empêchez tye garbage collector d'avoir à trouver des clusters d'obects qui ont plus de chemins vers une racine.

 1
Author: rsp, 2009-10-17 14:02:09

Lorsque la JVM n'a pas d'espace mémoire nécessaire pour s'exécuter, garbage collector s'exécute et supprime les objets inutiles et alloue de la mémoire à la JVM.

Les objets inutiles sont les objets qui n'ont pas de référence (adresse) pour cela.

Il y a principalement 4 points pour les objets éligibles au garbage collector.

  1. Null Référencement

    Garbage collector peut supprimer un objet lorsque la variable de référence de l'objet est attribué null comme il est valeur

        A a = new A();
        a = null;
    
  2. Réaffectation de

    Lorsqu'un autre objet est affecté à la variable de objet l'ancien objet référencé peut être supprimé par garbage collecteur.

      A a = new A(100);
      a =new A(200);
    
  3. Portée locale

    Si un objet est créé à l'intérieur d'un bloc, cet objet est éligible garbage collector à côté de ce bloc.

      if(condition){
    
         A a = new A();
    
      }
    
  4. Isolement

    Un objet peut faire référence à un autre objet mais il doit y en avoir au moins un référence (adresse) variable pour ces objets dans la pile, sinon tous ces objets sont éligibles pour garbage collector.

          class A{
                A r;
                A(int i){
                 //something   
               }
          } 
    
          A a1 = new A(100);
          a1.r = new A(101);
          a1.r.r = new A(102);
          a1.r.r.r = a1;
    
          a1  = null //all ojects are eligible to garbage collector  
    
 0
Author: Nisal Edu, 2017-11-05 01:41:12