Sind statische Felder für die Speicherbereinigung geöffnet?

95

Bei einer hypothetischen Utility-Klasse, die nur beim Programm-Setup verwendet wird:

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

Wird myObject als Müll gesammelt, wenn es nicht mehr verwendet wird, oder bleibt es für die gesamte Lebensdauer des Programms erhalten?

Michael Deardeuff
quelle

Antworten:

112

Statische Variablen können nicht für die Speicherbereinigung ausgewählt werden, während die Klasse geladen wird. Sie können gesammelt werden, wenn der jeweilige Klassenlader (der für das Laden dieser Klasse verantwortlich war) selbst für Müll gesammelt wird.

Lesen Sie den JLS-Abschnitt 12.7 Entladen von Klassen und Schnittstellen

Eine Klasse oder Schnittstelle kann nur dann entladen werden, wenn ihr definierender Klassenlader vom Garbage Collector zurückgefordert werden kann. [...] Vom Bootstrap-Loader geladene Klassen und Schnittstellen dürfen nicht entladen werden.

bruno conde
quelle
@bruno, Bedeutet Ihr Link, dass ein Klassenlader einen Verweis auf jede Klasse enthält, die er lädt, auch wenn die geladene Klasse keine statischen Mitglieder hat?
Pacerier
@brunoconde, ich glaube nicht, dass das wirklich stimmt. Welcher Absatz besagt das genau? (Bitte setzen Sie die Diskussion auf stackoverflow.com/questions/405364/… fort. )
Pacerier
Wenn der Klassenlader für die Speicherbereinigung berechtigt wäre. ?
Rohit Bandil
@RohitBandil - wenn es nicht erreichbar ist.
Stephen C
55

Statische Variablen werden von Klassenobjekten referenziert, auf die von ClassLoaders verwiesen wird Vielmehr werden die Objekte, auf die sie verweisen, nicht gesammelt.

Jon Skeet
quelle
1
Werden ClassObjekte, die keine statischen Variablen enthalten, von ihrem Klassenladeprogramm referenziert?
Pacerier
14

Wenn Sie möchten, dass ein temporäres Objekt für die statische Initialisierung verwendet und dann entsorgt wird, können Sie einen statischen Initialisierungsblock verwenden, z

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

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

Da der statische Initialisiererblock eine spezielle statische Methode ist, ist myObject eine lokale Variable und kann nach Abschluss der Ausführung des Blocks als Müll gesammelt werden.

finnw
quelle
13

myObject ist eine Referenz und kein Objekt . Ein Objekt wird automatisch durch Müll gesammelt, wenn kein Verweis darauf verweist, da es nicht erreichbar ist.

So kann auch das Objekt hinter einer statischen Referenz "myObject" Müll gesammelt werden, wenn Sie es mit dereferenzieren

myObject = null;

und es gibt keine anderen Verweise auf dieses Objekt.

Statische Referenzen und Variablen bleiben jedoch für die Lebensdauer Ihres Programms erhalten.

Felix Keil
quelle
Willkommen bei StackOverflow! Das Setzen des Objekts nullauf das Ende von static blockist eine praktikable Option. In meinem Fall musste die Lebensdauer des Objekts jedoch länger sein als der statische Block. Das Ende der Nützlichkeit des Objekts war nicht sehr konkret; daher meine frage nach der verwendung des müllsammlers.
Michael Deardeuff
7

Ich denke, dies beantwortet Ihre Frage - im Grunde nicht, es sei denn, die Klasse stammt von einem speziellen Klassenlader und entlädt die Klasse.

Tom
quelle
0

Der Schlüssel hier ist die Garbage Collection von Klasseninstanzen, dh Objekte. Die ClassLoader-Instanz ist im Wesentlichen ein Objekt. Wenn das Classloader-Objekt also nicht müllsammelbar ist, werden alle im Heap gespeicherten Referenzen (dh statische Daten) fast nie müllsammelbar sein. Die Ausnahme ist der String-Pool.

Bevor Sie sich plötzlich dazu entschließen, überlegen private static MyGiantClass myGiantObject = new MyGiantClass() Sie zweimal, wie ich es auf die harte Tour gelernt habe.

ha9u63ar
quelle