2009-08-24 7 views
7

Ici beaucoup de gens sont confus,Où CLR stocke-t-il des classes statiques?

La classe normale stocke ses données dans le tas droit? Et la référence (Pointer) à la pile.

Lorsque la pile tombe hors de la portée, la prochaine fois que le garbage collector entre en jeu et supprime la mémoire du tas.

Maintenant, dans le cas de classes statiques, la mémoire ne peut pas être nettoyée par le garbage collector, car il doit y être l'ensemble du programme. Et il n'y a aucun moyen d'obtenir la référence en premier lieu.

Alors quand nous appelons la console. Écrire, par exemple? D'où le programme tire-t-il sa référence (Où conserve-t-il la référence à la classe statique)? Ou il l'appelle directement, mais comment?

+4

Je ne comprends pas une partie de cette question. Qu'entendez-vous par "sa valeur" et "son ref"? –

+0

Je pense qu'il parle de la façon dont il sépare le code exécutable des membres de données. –

+1

Parmi d'autres questions, c'est "son". – jason

Répondre

16

Je pense que vous êtes prête à confusion avec des classes où la vit avec mémoire comment la mémoire est maintenue sur. Lorsque vous créez une instance d'une classe normale, la mémoire de cette instance reste sur le tas. Une référence à cette instance peut se trouver dans un objet sur le tas (si vous définissez une variable membre dans une instance différente d'un objet); ou une variable de pile (si vous avez déclaré une variable à l'objet dans une méthode ou l'avez passée à un appel de fonction), ou elle peut être dans la liste des racines globales (s'il s'agit d'une référence statique, par exemple une référence Singleton).

Une classe statique ne peut pas être instanciée. Il n'y a pas de "référence" à la classe n'importe où (sauf pour les informations de type). Ses méthodes ne sont que des fonctions chargées en mémoire lorsque le CLR charge l'assemblage. Vous pouvez créer un délégué qui pointe vers l'une de ces méthodes, mais cela ne fait pas non plus référence à une instance de la classe. C'est juste un pointeur sur une fonction.

Par exemple, regardez ce code:

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

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

La principale méthode crée une instance d'une classe ObjectWrapper. Cette instance vit sur le tas.

À l'intérieur de l'instance ObjectWrapper, il existe une instance de classe Object qui réside sur le tas. La référence à cette classe est à l'intérieur de l'instance, donc je suppose que vous pourriez penser à la référence comme "vivant dans le tas".

Maintenant, comparez cela le code suivant:

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

L'instance de l'objet Singleton vit sur le tas, aussi. Cependant, la référence est une référence statique. Il est maintenu par le CLR dans une liste de références globales ou "root".

Regardez maintenant cette classe statique:

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

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

HelperMethods est une classe statique. Vous ne pouvez pas instancier la classe HelperMethods. Il ne peut y avoir aucun objet de cette classe sur le tas. Toutefois, dans la méthode DoSomethingUseful, il a deux références à une instance de la classe ObjectWrapper sur la pile. Un est passé, et un est déclaré à l'intérieur de la méthode.

+0

+1, apprécié le détail. – user7116

+0

En ce qui concerne les racines, consultez cet article qui explique l'algorithme GC de .NET et clarifie comment les racines ont un rôle dans le GC. http://msdn.microsoft.com/en-us/magazine/bb985010.aspx – felideon

+0

Il y a plusieurs points dans cette réponse qui ne sont pas entièrement précis. D'une part, l'affirmation «Il n'y a pas de référence» à «n'importe où» est incorrecte. Une référence à chaque type, statique ou autre, est conservée sur un tas de chargeur. Le système de type entier est géré sur un tas de chargeur, avec des références aux types et à leurs membres. En outre, 'Cette classe ne consommera jamais de mémoire sur le tas' est également incorrecte ... alors qu'elle ne consomme pas d'espace de segment de mémoire GC, elle consomme de l'espace de tas sur un segment de chargement. L'idée d'une référence étant simplement un pointeur est également incorrecte ... le CLR utilise de nombreux niveaux d'indirection. – jrista

6

Pour vous donner une réponse simple, les classes statiques sont "stockées" sur ce qu'on appelle un tas de chargeur.Les tas de chargeurs sont des soins spéciaux, non GC qui ont des taux de croissance extrêmement prévisibles et stricts. Lors du démarrage d'une application .NET, plusieurs AppDomains sont créés. Outre le domaine de l'application principale, il existe des domaines d'application système et partagé qui contiennent les espaces de noms système et mscorelib, des segments spéciaux (tels que les segments de chargement) et le CLR lui-même.

Pour une explication très détaillée, lisez l'article MSDN Magazine suivant:

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

En dépit d'être d'il y a quelques années, il est toujours valable. (Cependant, je ne peux pas dire si. NET 4.0 a changé autant.)

Questions connexes