Quelles sont les racines?

Quelles sont les racines de la collecte des ordures?

J’ai lu la définition de root comme “toute référence à laquelle vous programmez peut accéder” et la définition de live est qu’un object en cours d’utilisation, qui peut être une variable locale, est une variable statique.

Je suis un peu confondu avec la distinction entre les objects root et les objects live.

Quel est le chemin d’access à la racine? Comment fonctionnent les objects root et live?

Quelqu’un peut-il élaborer?

Si vous considérez les objects en mémoire comme un arbre, les “racines” seraient les nœuds racine – chaque object immédiatement accessible par votre programme.

Person p = new Person(); p.car = new Car(RED); p.car.engine = new Engine(); p.car.horn = new AnnoyingHorn(); 

Il y a quatre objects; une personne, une voiture rouge, son moteur et son klaxon. Dessine le graphe de référence:

  Person [p] | Car (red) / \ Engine AnnoyingHorn 

Et vous vous retrouverez avec Person à la “racine” de l’arbre. Il est actif car il est référencé par une variable locale, p , que le programme peut utiliser à tout moment pour faire référence à l’object Person . Cela vaut également pour les autres objects, via p.car , p.car.engine , etc.

Puisque la Person et tous les autres objects connectés de manière récursive sont actifs, il y aurait des problèmes si le GC les collectait.

Considérez cependant si ce qui suit est exécuté après un certain temps:

 p.car = new Car(BLUE); 

Et redessinez le graphique:

  Person [p] | Car (blue) Car (red) / \ Engine AnnoyingHorn 

Maintenant, la Person est accessible via p et la voiture bleue via p.car , mais il est impossible d’accéder à la voiture rouge ou à ses composants – ils ne sont pas connectés à une racine active. Ils peuvent être collectés en toute sécurité.

Il s’agit donc de prendre chaque sharepoint départ (toutes les variables locales, globales, statiques, tout ce qui se trouve dans les autres threads et tous les frameworks de stack) – chaque racine – et de suivre récursivement toutes les références pour constituer une liste de tous les objects objects qui sont en cours d’utilisation et impropres à la suppression. Tout le rest est des ordures, en attente d’être collectées.

Les racines GC (Garbage Collector) sont des objects spéciaux pour le garbage collector. Le ramasse-miettes collecte les objects qui ne sont pas des racines GC et qui ne sont pas accessibles par des références provenant de racines GC.

Il existe plusieurs types de racines GC. Un object peut appartenir à plus d’un type de racine. Les racines sont:

  • Classe – classe chargée par le chargeur de classe système. Ces classes ne peuvent jamais être déchargées. Ils peuvent contenir des objects via des champs statiques. Veuillez noter que les classes chargées par des chargeurs de classes personnalisés ne sont pas des racines, sauf si les instances correspondantes de java.lang.Class sont des racines d’autres types.
  • Thread – live thread
  • Stack Local – variable locale ou paramètre de la méthode Java
  • JNI Local – variable locale ou paramètre de la méthode JNI
  • JNI Global – référence mondiale JNI
  • Monitor Used – objects utilisés comme moniteur pour la synchronisation
  • Détenu par JVM – objects détenus par JVM pour la récupération de place. En fait, la liste de ces objects dépend de l’implémentation de JVM. Les cas connus possibles sont: le chargeur de classe système, quelques classes d’exception importantes connues de la JVM, quelques objects pré-alloués pour la gestion des exceptions et des chargeurs de classes personnalisés lorsqu’ils sont en train de charger des classes. Malheureusement, JVM ne fournit absolument aucun détail supplémentaire pour de tels objects. Il appartient donc à l’analyste de décider à quel cas appartient un certain “Held by JVM”.

(crédit sur le site de YourKit )

YourKit ne mentionne pas le fait que les objects en attente de finalisation seront conservés en tant que racines jusqu’à ce que le GC exécute la méthode finalize finalize() . Cela peut provoquer une rétention transitoire de grands graphiques de manière inattendue. La règle générale est de ne pas utiliser les finaliseurs (mais c’est une question différente).

Racines ou racines de récupération de la mémoire sont les objects toujours accessibles . Si un object est toujours accessible, il ne peut pas être récupéré. les racines ne sont donc toujours pas éligibles à la collecte. C’est le jeu initial d’objects à partir duquel est déterminée l’accessibilité de tous les autres objects sur le tas.

Les autres objects du tas accessibles à partir des racines de la corbeille sont considérés comme des objects actifs et inéligibles à la collecte. les objects inaccessibles peuvent être marqués pour récupération.

Je connais plus Java que la plate-forme .Net, alors je ne parlerai que pour une seule. Sur la plateforme Java, les racines du GC dépendent en réalité de l’implémentation. Dans la plupart des runtime, les racines du GC ont tendance à être les opérandes sur la stack (car elles sont actuellement utilisées par les threads) et les membres de classe (statiques) des classes. L’accessibilité est calculée à partir de ces objects dans la plupart des JVM. Il existe d’autres cas où les parameters et les opérandes locaux utilisés par les appels JNI seront considérés comme faisant partie de l’ensemble racine, et également utilisés pour calculer l’accessibilité.

J’espère que cela élimine tout doute persistant sur ce qu’est une racine (ensemble) et sur ce qu’est un object vivant.

Le site Web IBM répertorie les éléments suivants en tant que racines du GC.

Notez que certaines d’entre elles sont des constructions artificielles effectuées par un parsingur de mémoire, mais qu’il est important de connaître si vous examinez un vidage de tas.

  • Classe système

    Une classe qui a été chargée par le chargeur de démarrage ou le chargeur de classe système. Par exemple, cette catégorie inclut toutes les classes du fichier rt.jar (partie de l’environnement d’exécution Java), telles que celles du package java.util. *.

  • JNI local

    Une variable locale en code natif, par exemple un code JNI défini par l’utilisateur ou un code interne JVM.

  • JNI global

    Une variable globale en code natif, par exemple un code JNI défini par l’utilisateur ou un code interne JVM.

  • Bloc de filetage

    Un object référencé à partir d’un bloc de thread actif.

  • Fil

    Un thread en cours d’exécution.

  • Moniteur occupé

    Tout ce qui a appelé les méthodes wait () ou notify (), ou qui est synchronisé, par exemple en appelant la méthode synchronisée (Object) ou en entrant une méthode synchronisée. Si la méthode était statique, la racine est une classe, sinon c’est un object.

  • Java local

    Une variable locale Par exemple, les parameters d’entrée ou les objects de méthodes créés localement qui sont encore dans la stack d’un thread. Pile native

    Paramètres d’entrée ou de sortie en code natif, par exemple code JNI défini par l’utilisateur ou code interne JVM. De nombreuses méthodes ont des parties natives et les objects gérés en tant que parameters de méthode deviennent des racines de récupération de mémoire. Par exemple, les parameters utilisés pour les opérations de fichier, de réseau, d’E / S ou de reflection.

  • Finaliseur

    Un object qui est dans une queue, en attente de l’exécution d’un finaliseur.

  • Non finalisé

    Un object qui a une méthode de finalisation, mais qui n’a pas été finalisé et qui n’est pas encore dans la queue du finaliseur.

  • Inaccessible

    Un object inaccessible par rapport à une autre racine, mais marqué comme racine par Memory Analyzer afin que l’object puisse être inclus dans une parsing.

    Les objects inaccessibles sont souvent le résultat d’optimisations de l’algorithme de récupération de place. Par exemple, un object peut être un candidat à la récupération de place, mais être si petit que le processus de nettoyage de la mémoire serait trop coûteux. Dans ce cas, l’object peut ne pas être récupéré et peut restr un object inaccessible.

    Par défaut, les objects inaccessibles sont exclus lorsque Memory Analyzer parsing le vidage du segment de mémoire. Ces objects ne sont donc pas affichés dans l’histogramme, l’arbre de dominateur ou les résultats de la requête. Vous pouvez modifier ce comportement en cliquant sur Fichier> Préférences …> Outils de diagnostic IBM pour Java – Analyseur de mémoire, puis en cochant la case Conserver les objects inaccessibles.

  • Cadre de stack Java

    Un cadre de stack Java, qui contient des variables locales. Ce type de racine de récupération de mémoire est généré uniquement si vous définissez les préférences pour traiter les frameworks de stack Java comme des objects. Pour plus d’informations, voir Java Basics: Threads et requêtes de stack de threads.

  • Inconnu

    Un object de type racine inconnu. Certains clichés, tels que les fichiers IBM Portable Heap Dump (.phd), ne disposent pas d’informations racine. Dans ce cas, l’parsingur Memory Analyzer marque les objects n’ayant aucune référence entrante ou inaccessibles de toute autre racine, comme inconnus. Cette action garantit que Memory Analyzer conserve tous les objects du vidage.

En Java, je dirais que les threads sont les objects racine. Chaque object vivant peut être retracé à un fil réel. Par exemple, un object statique est référencé par une classe, référencée par un chargeur de classe, référencé par une autre classe, référencée par une instance de cette classe, référencée par un Runnable référencé. par un fil vivant. ( Notez que les classes peuvent être GC’ed, elles ne peuvent pas être des racines )

Nous pouvons également considérer une racine “réelle” pour tous les threads, mais cela est hors du domaine de Java standard. Nous ne pouvons pas dire ce que c’est, et comment il fait référence à tous les threads.