2009-03-13 5 views

Antwort

76

Statische Methoden sind nur Methoden, sie werden nicht auf dem Heap gespeichert, sie können einfach keinen "this" Parameter verwenden.

Statische Variablen dienen als "Wurzeln" zum GC. Wenn Sie sie nicht explizit auf null setzen, bleiben sie so lange bestehen, wie das Programm läuft, und alles, was von ihnen erreichbar ist.

Eine Situation wird nur als Speicherverlust angesehen, wenn Sie beabsichtigen, dass der Speicher frei wird und nicht frei wird. Wenn Sie beabsichtigen, dass Ihre statische Variable einen Verweis auf ein Objekt für einen Teil der Zeit enthält und Sie vergessen, sie auf Null zu setzen, wenn Sie mit diesem Objekt fertig sind, würden Sie wahrscheinlich mit einem Leck enden. Wenn Sie es jedoch in die statische Variable einfügen und beabsichtigen, dass es dort ist, solange das Programm läuft, dann ist es definitiv kein Leck, es ist eher ein "permanenter Singleton". Wenn das Objekt zurückgewonnen wurde, während es noch existieren sollte, wäre das sehr schlecht gewesen.

Was Ihre Frage zum Heap betrifft: Alle Objekte in Java existieren entweder auf dem Heap oder auf dem Stack. Objekte werden auf dem Heap mit dem neuen Operator erstellt. Ein Verweis wird ihnen dann beigefügt. Wenn die Referenz null wird oder außerhalb des Gültigkeitsbereichs liegt (z. B. Ende des Blocks), erkennt der GC, dass es keine Möglichkeit gibt, das Objekt jemals wieder zu erreichen und es zurückzufordern. Wenn sich Ihre Referenz in einer statischen Variablen befindet, fällt sie niemals außerhalb des Bereichs, aber Sie können sie immer noch auf null oder auf ein anderes Objekt setzen.

+0

IIRC Die statischen Felder werden angezeigt, sobald die Klasse, die sie deklariert, GCed ist.Wenn die elast-Instanz der Klasse nicht mehr existiert, wird die Klassendeklaration und die statischen Felder mitgenommen. – ordnungswidrig

+1

Ich bin mir nicht sicher, ob @ o11rig völlig korrekt ist, aber ich glaube, dass der GC Statiken für Klassen erfassen darf, die unter bestimmten Umständen keine Mitglieder haben. Ich habe das aus ein paar Quellen gehört, aber nie eine genaue Erklärung gehört. –

+0

Geringfügige Fehler: Alle Java * -Objekte * leben im Heap. Object * references * und Primitive können auf dem Stack gespeichert werden, wenn sie Locals der gerade ausgeführten Methode sind und ansonsten im Heap gespeichert werden. (Außer in jeder modernen JVM mit einem JIT, wo der JIT-Optimierer Objekte beliebig platzieren kann, solange es noch * handelt * wie die Objekte auf dem Haufen sind.) Und es könnte argumentiert werden, dass statische Methoden - oder zumindest der Java-Bytecode, der sie implementiert - lebt auch auf dem Heap als Teil des Class-Objekts, das die Klasse repräsentiert, in der sie definiert wurden. –

1

Solange Sie diese Variablen von irgendwo im Code beziehen können, kann es nicht durch GCed, was bedeutet, dass sie dort bis zum Ende der Anwendung sein wird.

Können Sie es ein Speicherleck nennen, würde ich es nicht ein Speicherleck nennen, normalerweise ist ein Speicherleck Speicher, den Sie normalerweise wiederherstellen, aber Sie nie tun, oder Sie nur einen Teil davon wiederherstellen. Auch Speicherlecks werden in der Regel in der Zeit schlechter (zB: Jedes Mal, wenn Sie eine Methode aufrufen, wird mehr Speicher "durchgesickert"). In diesem Fall ist die Speicherauslastung für diese Variablen jedoch (irgendwie) statisch.

+0

Es ist nicht notwendig, dass statische Variablen aus Ihrem Code referenziert werden ... der Klassenlader hält permanent eine Referenz und daher wird der GC niemals eingreifen. – ReneS

1

Es wird nicht ein Speicherleck im klassischen C Sinne verursacht ... Zum Beispiel

Class A{ 

static B foo; 

... 

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

In diesem Fall wird ein Aufruf an makeFoo() führt nicht zu einem Speicherverlust, da die erste Instanz kann Müll gesammelt werden.

2

Objekte, die direkt oder indirekt durch Statik referenziert werden, verbleiben auf dem Heap, bis der entsprechende Klassenlader erfasst werden kann. Es gibt Fälle (z. B. ThreadLocal), bei denen andere Objekte indirekt auf den Klassenlader verweisen, sodass dieser nicht abgeholt wird.

Wenn Sie eine statische Liste haben, sagen Sie, und fügen Sie Referenzen dynamisch hinzu, dann können Sie sehr leicht mit "Objekt Lifetime Contention Issues" enden. Vermeiden Sie veränderbare Statik aus vielen Gründen.

3

Wenn Sie eine statische hashmap haben und Daten hinzufügen ... werden die Daten nie verschwinden und Sie haben ein Leck - falls Sie die Daten nicht mehr brauchen. Wenn Sie die Daten brauchen, ist es kein Leck, sondern ein riesiger Speicher.

+0

Angenommen, statische hashmap hat viele Objekte; und ich habe die Referenz der Karte auf null gesetzt (nicht alle Objekte, die es enthält)? ist es ein Speicherleck? da Sie angegeben haben, dass "der Klassenlader permanent eine statische Referenz enthält und daher der GC niemals eingreift"? –

+0

Wenn Sie den statischen Verweis auf null setzen und diese Map nirgendwo anders referenziert haben, wird der Speicher freigegeben. Die referenzierten Objekte in dieser Zuordnung werden ebenfalls freigegeben, wenn sie nicht von einer anderen Person referenziert werden. – ReneS