Les champs statiques sont-ils ouverts pour le garbage collection?

95

Étant donné une classe d'utilité hypothétique qui n'est utilisée que dans la configuration du programme:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

myObject sera-t-il récupéré lorsqu'il n'est plus utilisé ou restera-t-il pendant toute la durée de vie du programme?

Michael Deardeuff
la source

Réponses:

112

Les variables statiques ne peuvent pas être choisies pour le garbage collection pendant que la classe est chargée. Ils peuvent être collectés lorsque le chargeur de classe respectif (qui était responsable du chargement de cette classe) est lui-même collecté pour les déchets.

Consultez la section JLS 12.7 Déchargement des classes et des interfaces

Une classe ou une interface peut être déchargée si et seulement si son chargeur de classe définissant peut être récupéré par le garbage collector [...] Les classes et interfaces chargées par le chargeur d'amorçage ne peuvent pas être déchargées.

bruno conde
la source
@bruno, Par votre lien, cela signifie-t-il qu'un chargeur de classe contient une référence à chaque classe qu'il charge, même si la classe chargée n'a pas de membres statiques?
Pacerier
@brunoconde, je ne pense pas que ce soit vrai en fait. Quel paragraphe précise cela? (Veuillez continuer la discussion sur stackoverflow.com/questions/405364/… )
Pacerier
Quand le chargeur de classe serait éligible pour le garbage collection. ?
Rohit Bandil
@RohitBandil - lorsqu'il est inaccessible.
Stephen C
55

Les variables statiques sont référencées par des objets Class qui sont référencés par ClassLoaders -so à moins que le ClassLoader ne supprime la classe d'une manière ou d'une autre (si cela est même possible) ou que le ClassLoader lui-même devienne éligible pour la collection (plus probablement - pensez à décharger les applications Web) les variables statiques (ou les objets auxquels ils font référence) ne seront pas collectés.

Jon Skeet
la source
1
Les Classobjets qui ne contiennent aucune variable statique sont-ils référencés par leur chargeur de classe?
Pacerier
14

Si vous voulez qu'un objet temporaire soit utilisé pour l'initialisation statique puis éliminé, vous pouvez utiliser un bloc d'initialisation statique, par exemple

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

puisque le bloc d'initialisation statique est un type spécial de méthode statique, myObject est une variable locale et peut être récupéré après l'exécution du bloc.

finnw
la source
13

myObject est une référence et non un objet . Un objet est automatiquement garbage collection lorsqu'aucune référence ne pointe vers lui car il est inaccessible.

Ainsi, l'objet derrière une référence statique "myObject" peut également être récupéré si vous le déréférencer avec

myObject = null;

et il n'y a aucune autre référence à cet objet.

Cependant, les références et variables statiques restent pour la durée de vie de votre programme.

Felix Keil
la source
Bienvenue dans StackOverflow! Définir l'objet nullà la fin de static blockest une option viable. Dans mon cas, cependant, la durée de vie de l'objet devait être plus longue que le bloc statique. La fin d'utilité de l'objet n'était pas très concrète; donc ma question sur l'utilisation du ramasse-miettes.
Michael Deardeuff
7

Je pense que cela répond à votre question - en gros pas à moins que la classe ne vienne d'un chargeur de classe spécial et que cela décharge la classe.

À M
la source
0

La clé ici est la récupération de place des instances de classe, c'est-à-dire des objets. L'instance ClassLoader est, par essence, un objet. Donc, si l'objet Classloader n'est pas garbage collection, toute référence d'entre eux stockée dans le tas (c'est-à-dire des éléments statiques) ne sera presque jamais garbage collect. L'exception est le pool de chaînes.

Alors avant de vous décider soudainement de faire private static MyGiantClass myGiantObject = new MyGiantClass() Réfléchissez à deux fois, car j'ai appris à la dure.

ha9u63ar
la source