2009-08-24 14 views
7

Hier sind viele Leute verwirrt,Wo speichert CLR statische Klassen?

Normale Klasse speichert ihre Daten in den Haufen richtig? Und die Referenz (Zeiger) auf den Stapel.

Wenn der Stapel außerhalb des Gültigkeitsbereichs liegt, tritt das nächste Mal der Garbage Collector ein und entfernt den Speicher vom Heapspeicher.

Jetzt im Falle von statischen Klassen, kann der Speicher nicht sauber durch den Garbage Collector sein, da es das gesamte Programm da sein muss. Und es gibt keine Möglichkeit, die Referenz überhaupt zu bekommen.

Also wenn wir Console aufrufen. Zum Beispiel schreiben? Woher erhält das Programm seine Referenz von (Wo speichert es den Verweis auf die statische Klasse)? Oder es nennt es nur direkt, aber wie?

+4

Ich verstehe keinen Teil dieser Frage. Was meinst du mit "seinem Wert" und "seinem Ref"? –

+0

Ich erwarte, dass er darüber spricht, wie ausführbarer Code von Datenmitgliedern getrennt wird. –

+1

Unter anderem ist es "es". – jason

Antwort

16

Ich glaube, Sie verwirrend Klassen mit sind, wo die Erinnerung lebt mit wie der Speicher auf bis gehalten wird. Wenn Sie eine Instanz einer normalen Klasse erstellen, befindet sich der Speicher dieser Instanz auf dem Heap. Ein Referenz zu dieser Instanz möglicherweise in einem Objekt auf dem Heap (wenn Sie eine Mitgliedsvariable in einer anderen Instanz eines Objekts darauf festlegen); oder eine Stapelvariable (wenn Sie eine Variable für das Objekt innerhalb einer Methode deklariert oder an einen Funktionsaufruf übergeben haben) oder in der Liste globaler Wurzeln (wenn es sich um eine statische Referenz handelt, z. B. eine Singleton-Referenz).

Eine statische Klasse kann nicht instanziiert werden. Es gibt keine "Referenz" auf die Klasse (außer Typinformationen). Seine Methoden sind nur Funktionen, die in den Speicher geladen werden, wenn die CLR die Assembly lädt. Sie könnten einen Delegaten erstellen, der auf eine dieser Methoden verweist, aber auch keinen Verweis auf eine Instanz der Klasse. Das ist nur ein Zeiger auf eine Funktion.

Zum Beispiel betrachten Sie diesen Code:

class ObjectWrapper 
{ 
    Object obj = new Object(); 
} 

static void Main(string[] args) 
{ 
    ObjectWrapper wrapper = new ObjectWrapper(); 
    ... 
} 

Die Main-Methode eine Instanz eines ObjectWrapper Klasse erstellt. Diese Instanz lebt auf dem Heap.

Innerhalb der ObjectWrapper-Instanz gibt es eine Instanz der Klasse Object, die sich auf dem Heap befindet. Die Referenz auf diese Klasse befindet sich in der Instanz, also könnte man sich die Referenz als "im Haufen leben" vorstellen.

Nun vergleichen Sie diese mit dem folgenden Code:

class Singleton 
{ 
    static readonly instance = new Singleton(); 
} 

Die Instanz des Singleton-Objekt auf dem Heap lebt auch. Die Referenz ist jedoch eine statische Referenz. Es wird von der CLR in einer Liste von globalen oder "root" -Referenzen verwaltet.

Nun ein Blick auf diese statische Klasse:

class ObjectWrapper 
{ 
    Object obj = new Object(); 
} 

static class HelperMethods 
{ 
    static int DoSomethingUseful(ObjectWrapper wrapper1) 
    { 
     ObjectWraper wrapper2 = wrapper1; 
     // code here 
    } 
} 

HelperMethods eine statische Klasse ist. Sie können die HelperMethods-Klasse nicht instanziieren. Es dürfen keine Objekte dieser Klasse auf dem Heap vorhanden sein. In der DoSomethingUseful-Methode hat es jedoch zwei Verweise auf eine Instanz der ObjectWrapper-Klasse im Stapel. Eins wird übergeben, und man wird innerhalb der Methode deklariert.

+0

+1, genossen das Detail. – user7116

+0

Soweit "Wurzeln" gehen, sehen Sie sich diesen Artikel an, der den GC-Algorithmus von .NET erklärt und verdeutlicht, wie Wurzeln eine Rolle in der GC spielen. http://msdn.microsoft.com/en-us/magazine/bb985010.aspx – felideon

+0

Es gibt mehrere Punkte in dieser Antwort, die nicht ganz genau sind. Zum einen ist die Aussage "Es gibt keine" Referenz "irgendwo" ist falsch. Ein Verweis auf jeden Typ, ob statisch oder nicht, wird auf einem Lade-Heap gespeichert. Das gesamte Typsystem wird auf einem Loader-Heap mit Verweisen auf Typen und ihre Member verwaltet. Auch "Diese Klasse wird niemals Speicher auf dem Heap verbrauchen" ist ebenfalls falsch. Während sie keinen GC-Heap-Speicher verbraucht, verbraucht sie Heap-Speicher auf einem Loader-Heap. Die Idee einer Referenz, die einfach ein Zeiger ist, ist auch falsch ... die CLR verwendet viele Ebenen der Indirektion. – jrista

6

Um Ihnen eine einfache Antwort zu geben, werden statische Klassen auf einem so genannten Loader Heap "gespeichert".Loader-Heaps sind spezielle, nicht-GC-Heilungen, die extrem vorhersagbare und strenge Wachstumsraten haben. Wenn eine .NET-Anwendung gestartet wird, werden tatsächlich mehrere Anwendungsdomänen erstellt. Zusätzlich zur primären Anwendungsdomäne gibt es Systemdomänen und freigegebene Anwendungsdomänen, die die Systemnamespaces und mscorelib, spezielle Heaps (wie die Loader-Heaps) und die CLR selbst enthalten.

Für eine voll detaillierte Erklärung, die folgende MSDN Magazin-Artikel lesen:

Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

Trotz von vor ein paar Jahren zu sein, gilt es nach wie vor. (Allerdings kann ich nicht sagen, ob sich .NET 4.0 so stark verändert hat.)