2010-07-21 12 views
1

J'ai une fuite de mémoire dans l'application web (servlet) sur laquelle je travaille. Je me méfie d'une cause et je voulais entendre vos idées à ce sujet. J'utilise des hashmaps, hashsets etc. comme DB (environ 20 Mo de données chargées). Ces cartes, ensembles sont rechargées une fois toutes les 10 min. Il y a énormément de demandes simultanées. J'ai lu que, GC passe des objets, qui ne sont pas collectés pour une période de temps/cycle, à une génération (générations anciennes et permanentes) qui est moins vérifiée ou ramassée. Je pense que mon utilisation pour les cartes statiques, les ensembles me cause un problème de fuite. Qu'est-ce que tu penses ?en utilisant le dictionnaire statique comme cache peut entraîner un problème de fuite?

+0

Tout d'abord merci pour les réponses. Je garderai vos suggestions à l'esprit. Voici quelques détails supplémentaires; Toutes les dix minutes je suis ces étapes 1) Je crée les nouvelles cartes (en tant que cartes temporaires) en arrière-plan. 2) Effacer les anciennes cartes en appelant la méthode .clear() (même les assigner à null avant de passer à l'étape 3) 3) Donner des références de nouvelles cartes aux anciennes cartes. Puis-je manquer quelque chose ici? – WorM

+0

Comment les éléments de votre code qui accèdent à ces cartes accèdent-ils réellement au contenu? Êtes-vous certain qu'aucun autre élément du code n'obtient une référence à la carte statique elle-même? Le stockage de l'application de données dans une variable statique est en quelque sorte une odeur de code et peut entraîner des problèmes de fuite très simplement, si elle n'est pas bien conçue. –

Répondre

1

Ce n'est pas une fuite si vous avez supprimé toutes les références. Si vous effacez entièrement votre carte, ce n'est pas la source d'une fuite. Vous devriez considérer le fait que la JVM choisit de ne pas utiliser la génération persistante de GC très souvent comme non pertinent pour vous - tout ce qui compte est que vous n'avez pas de référence, donc la JVM pourrait GC si elle le souhaite.

Il existe différentes stratégies que les JVM peuvent utiliser pour gérer le GC, donc je parle ici de généralités plutôt que de détails, mais GCing tenured spaces a tendance à être très cher et a un impact important sur l'application, donc la JVM choisit ne pas le faire souvent en général.

Si vous examinez la quantité d'espace mémoire utilisée, vous verrez un motif en dents de scie à mesure que des éléments sont ajoutés et éventuellement collectés. Ne vous inquiétez pas de l'endroit où se trouve le haut de la dent de scie, soyez préoccupé par l'endroit où se trouve le fond (et à quelle distance de la quantité maximale d'espace de tas disponible). Une façon de tester si c'est vraiment une fuite est de tester votre application pendant une longue période. Si vous avez une fuite, la quantité de mémoire de base utilisée par votre application augmentera avec le temps (le fond de la dent de scie). Si vous ne le faites pas, cela restera constant. Si vous avez une fuite, vous pouvez utiliser un profileur pour vous aider à le trouver.

1

Les cartes statiques sont une source connue de fuites. La raison en est que les gens mettent des choses et ne les enlèvent pas. Si toutes les dix minutes, il vous suffit de vider le cache, puis recharger, alors ça devrait aller.

Je parie que vous ne l'effacez pas correctement. La partie GC fonctionne correctement, je ne m'inquiéterais pas que c'est le problème.

0

Vous pouvez également envisager d'utiliser WeakReference si vous avez un moyen de retomber dans les données réelles si une partie de votre cache est GC-ed mais ensuite nécessaire. Comme l'a noté Romain, la carte statique est un suspect.

2

Si pour une raison quelconque, vous ne pouvez pas nettoyer régulièrement jusqu'à explicitement, vous pouvez envisager d'utiliser un WeakHashMap à la place, qui est

Une mise en œuvre de la carte en fonction Hashtable avec clés faibles. Une entrée dans un WeakHashMap sera automatiquement supprimée lorsque sa clé n'est plus utilisée normalement. Plus précisément, la présence d'un mappage pour une clé donnée n'empêchera pas la clé d'être rejetée par le garbage collector, c'est-à-dire rendue finalisable, finalisée puis récupérée. Lorsqu'une clé a été supprimée, son entrée est effectivement supprimée de la carte. Cette classe se comporte donc différemment des autres implémentations de Map.

Malheureusement, depuis Java6, il ne semble pas y avoir de WeakHashSet dans la bibliothèque standard, mais plusieurs implémentations peuvent être trouvées sur le réseau.

0

Je vous suggère de vérifier le contenu du tas à l'aide d'une pile de mémoire et d'un analyseur de tas (tel que JVisualVM). Cela vous aidera à trouver des suspects de fuite. Le fait que l'ancienne génération soit collectée moins fréquemment ne signifie pas que plus de mémoire fuit; Rappelez-vous que, même si cela peut sembler plein, seulement une partie représente des objets vivants, et l'autre partie est effacée par le GC principal suivant. Comme d'autres l'ont dit, le problème peut être dû au nettoyage incomplet des collections statiques.

La génération permanente ne reçoit jamais d'objets promus. Il s'agit d'une zone hors-réserve réservée à d'autres fins, telles que les informations réfléchies des classes chargées et les chaînes internées.