In che modo esattamente i campi statici funzionano internamente?

Di 'che hai una lezione,

class Foo { public static bar; } 

Quando dici:

 new Foo(); 

Posso immaginare che nella memory, uno spazio è riservato per questo object.

… e quando ripeti:

 new Foo(); 

… beh ora hai un altro spazio disponibile per l'object.

Tuttavia, where vive esattamente il field statico?

Quello che sto davvero cercando di imparare è:

In che modo i riferimenti agli oggetti fanno riferimento allo stesso field degli oggetti a cui fanno riferimento?

Mentre i dettagli esatti del sistema di tipi dipendono dall'implementazione, lasciathemes entrare in qualche dettaglio in più rispetto al solo affermare che ciò dipende e non dovresti preoccupartene . Descriverò come funziona approssimativamente nell'implementazione di Microsoft (.NET) secondo il libro CLR via C # di Jeffrey Richter e l'articolo Vedi come il CLR crea oggetti di runtime di Hanu Kommalapati et al. (numero originale MSDN di maggio 2005 ).


Dì che hai una class:

 class Foo { // Instance fields string myBar = "Foobar"; int myNum; // Static fields static string bar = "Foobar"; static int num; } Foo myFoo = new Foo(); Type typeOfFoo = typeof(Foo); 

Dove vivono i campi dell'istanza?

Ogni volta che si dice new Foo() , lo spazio viene allocato e inizializzato per l'istanza dell'object e viene chiamato il constructor. Questa istanza è mostrata come esempio di Foo nell'image sottostante. Tale istanza contiene solo i campi di istanza della class (in questo caso myBar e myNum ) e per gli oggetti allocati nell'heap due campi aggiuntivi utilizzati dal runtime ( Sync block index e Type handle ). L'handle del tipo è un puntatore a un object Type che descrive il tipo dell'istanza, in questo caso il tipo di Foo .

Quando dici di new Foo() , viene allocato un nuovo spazio che di nuovo contiene spazio per i campi di istanza del tipo. Come puoi vedere, i campi di istanze sono associati alle istanze dell'object.

Il runtime inserisce ciascun field di istanza in un offset fisso dall'inizio dei dati dell'object. Ad esempio, myBar potrebbe vivere con offset +4. L'indirizzo del field dell'istanza è semplicemente l'indirizzo dell'object più l'offset del field.

Dove vivono i campi statici?

I campi statici in C # e Java non sono associati ad alcuna istanza di object, ma con un tipo. Classi, strutture ed enumerazioni sono esempi di tipi. Solo una volta (per tipo) è uno spazio allocato per contenere i valori dei campi statici. Avrebbe senso allocare spazio per i campi statici nella struttura Type che descrive il tipo, poiché esiste anche un solo object Type per tipo. Questo è l'approccio adottato da C # e Java.

L'object Type 1 viene creato quando il tipo viene caricato dal runtime. Questa struttura contiene tutti i tipi di informazioni necessarie affinché il runtime sia in grado di allocare nuove istanze, call methods ed eseguire casting, tra le altre cose. Contiene anche lo spazio per i campi statici, in questo caso bar e num .

Il runtime ha inserito each field statico in un certo offset dall'inizio dei dati del tipo. Questo è diverso per each tipo. Ad esempio, la bar potrebbe vivere con offset +64. L'indirizzo del field statico è l'indirizzo dell'object Type più l'offset del field. Il tipo è staticamente noto.

Mostra alcune strutture dell'oggetto e le loro relazioni.

1 ) In Microsoft .NET, più strutture diverse descrivono un tipo, come MethodTable e le strutture EEClass .

Questo dipende completamente dall'implementazione in questione. Per C # e Java, il runtime è autorizzato a determinare where archiviare la memory per la variabile. Per C e la maggior parte dei linguaggi compilati, il compilatore prende questa decisione.

Detto questo, in pratica, non import . L'utilizzo è determinato dalla specifica, quindi sei libero di utilizzare la variabile sapendo che il comportmento sarà garantito.

Ciò varia selvaggiamente da una lingua all'altra e può persino variare selvaggiamente da una piattaforma all'altra …

Ad esempio, sul lato .NET, i membri statici sono "associati" alla definizione di EEClass governa, che può essere un OR allocata EEClass o un membro assegnato "dovunque" (la specifica C # non specifica il comportmento heap / stack, è un dettagli di implementazione della VM)

Per Java, gli oggetti a cui fanno riferimento i campi statici risiedono nell'heap come altri oggetti:

L'heap è l'area dati di runtime da cui viene allocata la memory per tutte le istanze e gli arrays di class.

Il field verrà inizializzato (se la dichiarazione contiene un'initialization) quando la class viene caricata , cosa che avviene immediatamente prima della prima occorrenza di una delle seguenti operazioni:

  • viene creata un'istanza della class.
  • viene invocato un metodo statico dichiarato dalla class.
  • viene assegnato un field statico dichiarato dalla class.
  • viene utilizzato un field statico dichiarato dalla class e il field non è una variabile costante (§4.12.4).

L'accesso al field statico avviene tramite 2 istruzioni speciali JVM, getstatic e putstatic . Ma a parte questa distinzione, i campi statici sono simili ai campi non statici.

Potrebbero esserci delle eccezioni, ma per i tipi di riferimento la new -keyword di solito crea un object in una struttura dati interna chiamata "heap". L'heap è gestito dal CLR (Common Language Runtime). Non fa differenza se hai un membro statico o di istanza o una variabile locale.

La differenza tra membri statici e membri di istanza (quelli senza la parola chiave static ) è che i membri statici esistono solo una volta per tipo (class, struct) ei membri di istanza esistono una volta per istanza (per object).

È solo il riferimento che è statico o no; questa distinzione non si applica all'object referenziato (a less che l'object non sia un tipo di valore). Un membro statico, un membro di istanza e una variabile locale possono fare riferimento allo stesso object.

Im solo familiarità con C #, e questa è la mia comprensione di questo:

Quindi il programma si avvia, carica tutti gli assembly correlati in un AppDomain. Quando viene caricato l'assambly, vengono chiamati tutti i costruttori statici, inclusi i campi statici. Vivranno lì e l'unico modo per scaricarli è scaricare AppDomain.

I membri statici e le costanti sono memorizzati nell'heap. A differenza degli oggetti nell'heap che possono get la garbage collection, i membri e le costanti statici rimangono fino a quando Appdomain non viene rimosso, quindi una volta dovresti fare attenzione nell'affrontare i campi statici

Dipende dalla lingua alla lingua o dal progettista della lingua. Se parlo di Java, i membri statici memorizzano nell'area Metodo della JVM e tutti gli oggetti sono collegati a loro. Un'altra cosa che è molto importnte sapere è che possiamo accedere al membro dei dati statici senza creare l'object della class. Significa che l'allocazione della memory ai membri dei dati statici non dipende dalla creazione dell'object di quella class.

Per specifica le variables statiche sono memorizzate in Costante . JVM memorizza queste informazioni in Permanent Generation.

Le variables statiche appartengono alla class e non all'object, quindi c'è solo una bar nella memory anche se si inizializzano migliaia di istanti di Foo .

In genere le variables statiche sono memorizzate sul segmento di dati della memory del programma. quindi per each class creata / è in esecuzione il programma creerà la variabile statica sul segmento di dati e tutte le altre variables verranno inizializzate nel segmento di codice.

quindi fondamentalmente è come

 +++++++++++++++++++++++++++++++++++++ + DATA Segment + -static vars + +---------------------------------- + instances | instances | instances| + | | | 

qui la singola area è condivisa tra le istanze.

da wikipedia "L'area dati contiene variables globali e statiche utilizzate dal programma
inizializzato esplicitamente con un valore. "