web-dev-qa-db-fra.com

Références circulaires dans Java

Compte tenu d'une agrégation d'instances de classe qui se rapportent dans un complexe, circulaire, de la mode: est-il possible que le collecteur des ordures puisse ne pas être capable de libérer ces objets?

Je rappelle vaguement que cela étant un problème dans la JVM dans le passé, mais je pensé Cela a été résolue il y a des années. Pourtant, une enquête à Jhat a révélé une référence circulaire la raison d'une fuite de mémoire que je suis maintenant confrontée.

Remarque: J'ai toujours eu l'impression que la JVM était capable de résoudre des références circulaires et de libérer de telles "îles de déchets" de la mémoire. Cependant, je pose cette question juste pour voir si quelqu'un a trouvé des exceptions.

48
Ryan Delucchi

Seule une implémentation très naïve aurait un problème de références circulaires. Wikipedia a un bon article sur les différents algorithmes de GC. Si vous voulez vraiment en savoir plus, essayez (Amazon) collection de déchets: algorithmes pour la gestion de la mémoire dynamique automatique . Java= a eu un bon collecteur des ordures depuis 1,2 et une excellente bonne dans 1,5 et Java 6.

La partie difficile d'améliorer GC est la réduction des pauses et des frais généraux, pas des choses de base telles que la référence circulaire.

42
David G

Ryan, à en juger par votre commentaire à références circulaires en Java , vous êtes tombé dans le piège des objets de référencement d'une classe, qui a probablement été chargé par le chargeur de classes de bootstrap/système. Chaque classe est référencée par le chargeur de classe qui chargait la classe et peut ainsi être collecté à la poubelle uniquement si le chargeur de classe n'est plus accessible. La capture est que le chargeur de classes de bootstrap/système n'est jamais collecté, par conséquent, des objets accessibles à partir de classes chargées par le chargeur de système de système ne peuvent être recueillies non plus.

Le raisonnement de ce comportement est expliqué dans JLS. Par exemple, la troisième édition 12.7 http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.7 .

12
Alexander

Si je me souviens bien, alors selon les spécifications, Il n'y a que des garanties sur ce que le JVM ne peut pas collecter (tout ce qui est accessible), pas ce qu'il va collecter.

À moins que vous ne travaillez avec JVM en temps réel, la plupart des collectionneurs à ordures modernes devraient pouvoir gérer des structures de référence complexes et identifier des "sous-graphes" pouvant être éliminés en toute sécurité. L'efficacité, la latence et la probabilité de faire cela s'améliorer au fil du temps alors que davantage d'idées de recherche font leur chemin dans des ordinateurs virtuels standard (plutôt que de recherche).

4
Uri

Le Java Spécification dit que le collecteur des ordures peut détenir votre objet uniquement s'il est pas accessible d'un thread.

Atteignable signifie qu'il y a une référence ou une chaîne de références qui mène de A à B, et peut aller via C, D, ... Z pour tout ce qu'il se soucie.

Le JVM ne collecte pas des choses n'a pas été un problème pour moi depuis 2000, mais votre kilométrage peut varier.

CONSEIL: Java Serialization met en cache des objets pour effectuer un transfert de maille d'objet efficace. Si vous avez de nombreux gros objets transitoires, et que toute votre mémoire est chargée, réinitialisez votre sérialisateur pour effacer son cache.

3
Tim Williscroft

Juste pour amplifier ce qui a déjà été dit:

L'application que j'ai travaillé depuis six ans récemment modifiée de Java 1.4 à Java 1.6, et nous avons découvert que nous devions ajouter Les références statiques aux choses que nous n'avions même pas réalisées étaient à la poubelle à collectionner auparavant. Nous n'avions pas besoin de la référence statique avant parce que le collecteur des ordures était suce, et c'est tellement mieux maintenant.

2
Paul Tomblin

Comptage de référence Les GC sont notoires pour ce problème. Notamment, Suns JVM n'utilise pas de référence Comptage de GC.

Si l'objet ne peut pas être atteint de la racine du tas (généralement au minimum, via les chargeurs de classe si rien d'autre00, les objets seront détruits car ils ne sont pas copiés lors d'un fichier typique Java = GC au nouveau tas.

2
Will Hartung

Le collecteur des ordures est un logiciel très sophistiqué - il a été testé dans une énorme suite Test JCK. Ce n'est pas parfait mais il y a une très bonne chance que tant que le Java Compiler (Javac) compilait toutes vos classes et JVM l'instanciez, alors vous devriez être bon.

Là encore, si vous souhaitez des références à la racine de ce graphique d'objet, la mémoire ne sera pas libérée, mais si vous savez ce que vous faites, vous devriez être correct.

0
anjanb