11
votes

Compte de référence en Java

J'ai un système qui continue à manquer d'espace disque car ce collecteur de déchets ne libère pas les objets qui maintiennent suffisamment les poignées du fichier. (Les fichiers sont créés et supprimés tout le temps, mais comme le processus dispose toujours d'une poignée de fichier ouverte, le système d'exploitation le garde sur le disque).

Les objets sont partagés, donc un simple essayer {...} enfin {Fermer (); } ne fera pas.

Il me semble que ma meilleure option consiste à implémenter le comptage de référence sur les objets et à fermer les poignées de fichier lorsque le nombre de références va à 0. Cependant, je suis réticent à la mettre en œuvre tout seul, car je suppose que là-bas sont des problèmes subtils en ce qui concerne la concurrence.

Malheureusement, Googling for "Comptage de référence en Java" n'apporte aucun résultat utile. Donc, ma question est la suivante: existe-t-il des ressources (articles, échantillons de code, bibliothèques) pouvant aider à mettre en œuvre le comptage de référence?


0 commentaires

3 Réponses :


3
votes

Vous pouvez effectuer un comptage de référence en enveloppant votre objet à l'intérieur d'un faim , puis à l'aide de la référence référence . Cependant, il semble que vous ne souhaitiez que découvrir lorsque votre poignée n'est plus référencée, vous n'avez donc pas besoin de compter du tout.

Mais la même méthode (c.-à-d. Un Afférence ) fera; juste fermer une poignée lorsque le référent devient null . Toutefois, vous aurez peut-être besoin d'une sous-classe sur mesure de faiblicielle avec une référence supplémentaire à la poignée de fichier, de sorte que vous puissiez la fermer (sinon, vous n'aurez pas accès à la poignée de fichier). Par exemple: xxx

Je n'ai pas vérifié cela complètement et je ne peux pas être sûr comment vous utilisez le fichier objet dans votre programme: i Supposons que vous partagiez un fichier instance autour de.


2 commentaires

Cela ne compte-t-il pas toujours sur le collecteur des ordures? Ne fait pas cela équivalent à la mise en œuvre d'un finaliseur? (Essayé, ne s'appelle pas assez vite).


Oui, cela dépend du gc mais est légèrement différent de finaliser . Dans mon expérience, ce dernier est dangereux pour un grand nombre d'objets, ou avec un débit élevé, car la finalisation ne peut souvent pas suivre le taux de création d'objets provoquant des problèmes de surmenage



9
votes

Ne dépendez pas du collecteur des ordures. Il est intentionnellement conçu pour ne pas être fiable.

Si "partagé" signifie que vous l'utilisez plusieurs endroits de votre code, vous ne pouvez pas simplement le fermer, je vous suggère de changer votre code pour avoir un pool central de fichiers, où vous pouvez "vérifier" une poignée de fichier à être utilisé dans votre code localement. La procédure Fermer () renvoie ensuite la poignée de fichier à la piscine. Gardez une trace de vos poignées lorsque toutes les poignées pour un fichier donné sont renvoyées dans la piscine, vous fermez le fichier pour bon.


2 commentaires

Cela ne fait rien pour répondre à la question réelle: comment est-ce que cela doit être mis en œuvre correctement ?


@AleksandrDubinsky Une implémentation «correcte» ne s'appuie pas sur le collecteur des ordures.



3
votes

Malheureusement, Googling pour "Comptage de référence en Java" n'apporte aucun résultat utile.

Malheureusement, cela continue d'être vrai 8 ans plus tard.

Mais, plus! J'ai sorti Netty's Comptage des bits de comptage de référence, les a polies un peu et les a transformés dans une bibliothèque distincte, Almson-refcount .

La fonctionnalité de comptage de référence de base est simple et directe. Il existe une seule classe de base, référencomedObject . Il a une seule méthode surestimable, détruire . Il fournit retenir et libérant qui gérent un compteur de référence interne à l'aide d'une atomicfielupdater à thread-sûre et efficace. version appelle détruire sur le même thread, et en raison de la sémantique de commande de mémoire entre différents appels vers libérer , vous n'avez pas besoin de vous inquiéter de La sécurité de votre détruire même dans une application multi-threadée. La classe implémente autoclotionable et fournit une méthode fermeture qui appelle simplement version . Cela lui permet d'être utilisé en essayant des ressources.

Il n'y a pas de mécanisme de finalisation qui essaie d'appeler détruire au cas où vous oublieriez d'appeler la sortie! La finalisation présente de gros défis, y compris des problèmes de concurrence et même une finalisation prématurée, en particulier dans le cas général. (Si vous insistez sur les finaliseurs, vous pouvez toujours les utiliser ou les performances supérieures java.lang.ref.cleaner .)

Au lieu de cela, il existe un système de détection de fuite intelligente. Il utilise un mécanisme similaire à la finalisation. Parce que sa seule responsabilité consiste à détecter des fuites et d'enregistrer des informations de débogage, vous n'avez rien à faire pour que cela fonctionne correctement (sauf le tourner sur).

Les principales choses modifiées vs Netty sont:

  • une classe de base utilisable réelle pour tous vos objets comptés de référence.
  • une interface plus élégante avec moins de méthodes.
  • Code plus simple et plus propre avec moins de cruft.
  • Améliorations apportées à la documentation, aux préréglages et à la sortie du détecteur de fuites.

0 commentaires