it-swarm.com.de

Ist variable = null, wird sie für die Speicherbereinigung festgelegt

Helfen Sie mir, einen Streit mit einem Kollegen beizulegen: Unterstützt das Festlegen einer Variablen oder Auflistung in Java den Nullwert bei der Speicherbereinigung und verringert die Speichernutzung? Wenn ich ein lang laufendes Programm habe und jede Funktion möglicherweise iterativ aufgerufen wird (möglicherweise tausende Male): Sollen alle Variablen darin auf Null gesetzt werden, bevor ein Wert an die übergeordnete Funktion zurückgegeben wird, kann dies die Heap-Größe/Speicherauslastung reduzieren?

51
ashurexm

Das ist alte Leistungsgeschichte. In 1.0 Tagen war es wahr, aber der Compiler und die JVM wurden verbessert, um die Notwendigkeit zu beseitigen (falls überhaupt einer vorhanden war). Dieser exzellente IBM Artikel behandelt die Details, wenn Sie interessiert sind: Java-Theorie und -Praxis: Garbage Collection und Leistung

58
sblundy

Aus dem Artikel:

Es gibt einen Fall, in dem die Verwendung der expliziten Nullung nicht nur hilfreich ist, sondern virtuell erforderlich ist, und in diesem Fall ist ein Verweis auf ein Objekt breiter angelegt, als von der Spezifikation des Programms verwendet oder als gültig angesehen wird. Dies umfasst beispielsweise die Verwendung eines statischen Felds oder eines Instanzfelds zum Speichern einer Referenz auf einen temporären Puffer anstelle einer lokalen Variablen oder die Verwendung eines Arrays zum Speichern von Referenzen, die möglicherweise von der Laufzeit erreichbar bleiben, jedoch nicht durch die implizierte Semantik des Programms.

Übersetzung: "explizit null" persistente Objekte, die nicht mehr benötigt werden. (Wenn Sie wollen. "Virtuell erforderlich" eine zu starke Aussage?)

7
Pete

Die Java VM Spec

12.6.1 Finalisierung implementieren Jedes Objekt kann durch zwei Merkmale charakterisiert werden: Es kann erreichbar sein, ist der Finalizer erreichbar oder nicht erreichbar und es kann auch nicht finalisiert, finalisierbar oder finalisiert sein.

Ein erreichbares Objekt ist ein Objekt, auf das in jeder möglichen fortlaufenden Berechnung von einem beliebigen Live-Thread aus zugegriffen werden kann . Die Optimierung von Transformationen eines Programms kann so gestaltet werden, dass die Anzahl der erreichbaren Objekte geringer ist als die Anzahl der Objekte, die naiv als erreichbar betrachtet werden. Ein Compiler oder Codegenerator kann sich beispielsweise dafür entscheiden, eine Variable oder einen Parameter festzulegen, die nicht mehr auf Null gesetzt wird, um zu bewirken, dass der Speicher für ein solches Objekt möglicherweise früher wiederhergestellt werden kann.

Diskussion

Ein anderes Beispiel hierfür ist der Fall, wenn die Werte in den Feldern eines Objekts in Registern gespeichert werden. Das Programm kann dann auf die Register anstelle des Objekts zugreifen und nie wieder auf das Objekt zugreifen. Dies würde bedeuten, dass das Objekt Müll ist.

Das Objekt ist erreichbar, wenn es an einer möglichen weiteren Berechnung beteiligt werden kann. Wenn Ihr Code also auf eine lokale Variable verweist und nichts anderes darauf verweist, können Sie das Objekt sammeln, indem Sie es auf null setzen. Dies würde entweder eine Nullzeigerausnahme geben oder das Verhalten Ihres Programms ändern, oder wenn Sie dies nicht tun, brauchen Sie die Variable nicht an erster Stelle.

Wenn Sie ein Feld oder ein Array-Element auf Null setzen, kann dies für einige Anwendungen möglicherweise sinnvoll sein, und der Speicher wird dadurch schneller beansprucht. Wenn case ein großes Array erstellt, um ein vorhandenes Array zu ersetzen, auf das durch ein Feld in einer Klasse verwiesen wird, wird das Feld vor dem Ersetzen mit Nullen belastet, wodurch der Speicher entlastet wird. 

Eine weitere interessante Funktion von Java ist, dass der Gültigkeitsbereich nicht in Klassendateien angezeigt wird. Daher ist der Gültigkeitsbereich für die Erreichbarkeit nicht relevant. Diese beiden Methoden erzeugen den gleichen Bytecode, sodass VM den Gültigkeitsbereich des erstellten Objekts überhaupt nicht sieht:

static void withBlock () {
    int x = 1;

    {
        Object a = new Object();
    }

    System.out.println(x+1);
}

static void withoutBlock () {
    int x = 1;

    Object a = new Object();

    System.out.println(x+1);
}
5
Pete Kirkham

Nicht unbedingt. Ein Objekt kann für die Garbage Collection verwendet werden, wenn es keine aktiven Threads mehr gibt, die einen Verweis auf das Objekt enthalten.

Lokale Variablen verlieren den Gültigkeitsbereich, wenn die Methode zurückkehrt, und es macht überhaupt keinen Sinn, lokale Variablen auf Null zu setzen. Die Variablen verschwinden trotzdem und wenn nichts anderes eine Referenz auf die Objekte enthält, auf die sich die Variablen beziehen, werden diese Objekte für die Müllabfuhr geeignet.

Der Schlüssel ist nicht nur das Betrachten von Variablen, sondern die Objekte, auf die sich diese Variablen beziehen, und herauszufinden, wo diese Objekte von Ihrem Programm referenziert werden.

3
Jesper

Es ist für lokale Variablen unbrauchbar, es kann jedoch nützlich/erforderlich sein, um Instanzvariablen zu löschen, die nicht mehr benötigt werden (z. B. nach der Initialisierung).

(Ja, ich weiß, wie man das Builder-Muster anwendet ...)

2
Rhangaun

Das könnte einige in einem Szenario wie dem folgenden nur Sinn machen:

public void myHeavyMethod() {
  List hugeList = loadHugeListOfStuff();  // lots of memory used
  ResultX res = processHugeList(hugeList); // compute some result or summary 
  // hugeList = null;  // we are done with hugeList
    ...
  // do a lot of other things that takes a LOT of time (seconds?)
  // and which do not require hugeList
   ...
}

Hier könnte () einen gewissen Nutzen haben, um die hugeList = null-Zeile zu entkommentieren, schätze ich.

Aber es wäre sicherlich sinnvoller, die Methode umzuschreiben (vielleicht in zwei Teile umzuwandeln, Oder einen inneren Geltungsbereich angeben).

1
leonbloy

Wenn Sie einen Objektverweis auf null setzen, wird er in Frage kommen für die Garbage Collection. Der Speicher wird nicht unbedingt freigegeben. Dies hängt davon ab, wann der Garbage Collector ausgeführt wird (abhängig von der JVM). Wenn der Garbage Collector ausgeführt wird, wird der Heapspeicher freigegeben, indem nur die Objekte gelöscht werden, die-igible für die Garbage Collection sind.

0
Saurabh