web-dev-qa-db-fra.com

L'utilisation de trop de variables statiques peut-elle provoquer une fuite de mémoire en Java?

Si mon application a trop de variables ou de méthodes statiques, alors selon la définition, elles seront stockées en tas. S'il vous plait corrigez moi si je me trompe

1) Ces variables seront-elles sur le tas jusqu'à la fermeture de l'application?
2) Seront-ils disponibles pour GC à tout moment? Sinon, puis-je dire que c'est une fuite de mémoire?

46
harshit

Les méthodes statiques ne sont que des méthodes, elles ne sont pas stockées sur le tas, elles n'ont tout simplement pas la possibilité d'utiliser un paramètre "this".

Les variables statiques servent de "racines" au GC. Par conséquent, à moins que vous ne les définissiez explicitement sur null, ils vivront aussi longtemps que le programme sera en vie, et tout est donc accessible depuis eux.

Une situation n'est considérée comme une fuite de mémoire que si vous avez l'intention de libérer de la mémoire et qu'elle ne le devient pas. Si vous prévoyez que votre variable statique contienne une référence à un objet pendant une partie du temps et que vous oubliez de la définir sur null lorsque vous avez terminé avec cet objet, vous vous retrouverez probablement avec une fuite. Cependant, si vous le mettez dans la variable statique et que vous souhaitez qu'il y soit aussi longtemps que le programme est en cours d'exécution, ce n'est certainement pas une fuite, il s'agit plus probablement d'un "singleton permanent". Si l'objet avait été récupéré alors que vous vouliez qu'il existe toujours, cela aurait été très mauvais.

Quant à votre question sur le tas: Tous les objets de Java existent soit sur le tas soit sur la pile. Les objets sont créés sur le tas avec le nouvel opérateur. Une référence leur est alors attachée. Si la référence devient nulle ou tombe hors de portée (par exemple, fin de bloc), le GC se rend compte qu'il n'y a aucun moyen d'atteindre cet objet à nouveau et le récupère. Si votre référence est dans une variable statique, elle ne sort jamais de portée, mais vous pouvez toujours le définir sur null ou sur un autre objet.

83
Uri

Si vous avez une table de hachage statique et que vous y ajoutez des données ... les données ne disparaîtront jamais et vous aurez une fuite - au cas où vous n'en auriez plus besoin. Si vous avez besoin des données, ce n'est pas une fuite, mais un énorme tas de mémoire qui traîne.

3
ReneS

Les objets référencés directement ou indirectement par la statique resteront sur le tas jusqu'à ce que le chargeur de classe approprié puisse être collecté. Il existe des cas (ThreadLocal, par exemple) où d'autres objets référencent indirectement le chargeur de classe, ce qui le rend non collecté.

Si vous avez une liste statique, par exemple, et y ajoutez des références de manière dynamique, vous pouvez très facilement vous retrouver avec des "problèmes de contention de durée de vie d'objet". Évitez la statique mutable pour de nombreuses raisons.

2

Tant que vous pouvez référencer ces variables quelque part dans le code, GCed ne peut pas le faire, ce qui signifie qu'elles seront là jusqu'à la fin de l'application.

Pouvez-vous appeler cela une fuite de mémoire, je n'appellerais pas cela une fuite de mémoire, généralement une fuite de mémoire est une mémoire que vous vous attendez normalement à récupérer mais que vous ne faites jamais, ou vous n'en récupérez qu'une partie. De plus, les fuites de mémoire s'aggravent généralement dans le temps (par exemple: chaque fois que vous appelez une méthode, il y a "fuite" de mémoire), mais dans ce cas, l'utilisation de la mémoire pour ces variables est (en quelque sorte) statique.

1
hhafez

Cela ne causera pas de fuite de mémoire au sens C classique ... Par exemple

Class A{

static B foo;

...

static void makeFoo(){
   foo = new B();
   foo = new B();
}

Dans ce cas, un appel à makeFoo () n'entraînera pas de fuite de mémoire, car la première instance peut être récupérée.

1
patros