wake-up-neo.com

Wie genau funktionieren statische Felder intern?

Sagen Sie, Sie haben eine Klasse, 

class Foo
{
    public static bar;
}

Wenn du sagst:

new Foo();

Ich kann mir vorstellen, dass im Speicher für dieses Objekt ein Platz reserviert ist. 

... und wenn Sie noch einmal sagen:

new Foo(); 

... nun haben Sie einen anderen Platz für das Objekt.

Wo genau lebt das statische Feld?

Was ich wirklich zu lernen versuche, ist:

Wie verweisen die Verweise auf die Objekte auf dasselbe Feld der Objekte, auf die sie verweisen?  

55
Koray Tugay

Während die genauen Details des Typsystems von der Implementierung abhängen, lassen Sie mich etwas mehr ins Detail gehen, als nur zu sagen, dass es hängt davon ab und Sie sollten sich nicht darum kümmern. Ich werde beschreiben, wie es in der Microsoft-Implementierung (.NET) ungefähr funktioniert, gemäß dem Buch CLR über C # von Jeffrey Richter und dem Artikel Siehe Wie die CLR Laufzeitobjekte erstellt von Hanu Kommalapati et al. ( ursprüngliche MSDN-Ausgabe Mai 2005 ).


Angenommen, Sie haben eine Klasse:

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);

Wo wohnen die Instanzfelder?

Wenn Sie new Foo() sagen, wird Speicherplatz für die Objektinstanz zugewiesen und initialisiert, und der Konstruktor wird aufgerufen. Diese Instanz wird im Bild unten als Instanz von Foo angezeigt. Eine solche Instanz enthält nur die Instanzfelder der Klasse (in diesem Fall myBar und myNum), und für Objekte, die auf dem Heap zugeordnet sind, zwei zusätzliche Felder, die von der Laufzeitumgebung verwendet werden (Sync block index und Type handle). Das Typ-Handle ist ein Zeiger auf ein Type-Objekt, das den Typ der Instanz beschreibt, in diesem Fall Typ von Foo.

Wenn Sie wieder new Foo() sagen, wird neuer Speicherplatz zugewiesen, der wiederum Platz für die Instanzfelder des Typs enthält. Wie Sie sehen können, sind Instanzfelder dem Objekt Instanzen zugeordnet.

Die Laufzeit setzt jedes Instanzfeld um einen festen Abstand vom Beginn der Objektdaten. Beispielsweise könnte myBar bei Offset +4 leben. Die Adresse des Instanzfeldes ist einfach die Adresse des Objekts plus den Offset des Feldes.

Wo wohnen die statischen Felder?

Statische Felder in C # und Java sind keiner Objektinstanz zugeordnet, sondern einem Typ. Klassen, Strukturen und Aufzählungen sind Beispiele für Typen. Nur einmal (pro Typ) wird Speicherplatz für die Werte der statischen Felder zugewiesen. Es wäre sinnvoll, den statischen Feldern in der Type-Struktur, die den Typ beschreibt, Platz zuzuweisen, da pro Typ auch nur ein Type-Objekt vorhanden ist. Dies ist der Ansatz von C # und Java.

Das Type-Objekt1 wird erstellt, wenn der Typ von der Laufzeitumgebung geladen wird. Diese Struktur enthält alle Arten von Informationen, die für die Laufzeit erforderlich sind, um unter anderem neue Instanzen zuordnen, Methoden aufrufen und Casting durchführen zu können. Es enthält auch den Platz für die statischen Felder, in diesem Fall bar und num.

Die Laufzeitumgebung hat jedes statische Feld etwas vom Beginn der Daten des Typs versetzt verschoben. Dies ist bei jedem Typ unterschiedlich. Beispielsweise könnte bar bei Offset +64 leben. Die Adresse des statischen Felds ist die Adresse des Type-Objekts zuzüglich des Offsets des Feldes. Der Typ ist statisch bekannt.

Displays some object structures, and their relationships.

1) In Microsoft .NET beschreiben mehrere unterschiedliche Strukturen einen Typ, beispielsweise die Strukturen MethodTable und EEClass.

98

Dies hängt völlig von der jeweiligen Implementierung ab. Für C # und Java kann die Laufzeit bestimmen, wo der Speicher für die Variable gespeichert werden soll. Für C und die meisten kompilierten Sprachen trifft der Compiler diese Bestimmung.

In der Praxis gesagt, spielt es keine Rolle . Die Verwendung wird durch die Spezifikation festgelegt, sodass Sie die Variable frei verwenden können, wenn Sie wissen, dass das Verhalten garantiert ist.

16
Reed Copsey

In Java befinden sich Objekte, auf die statische Felder verweisen, auf dem Heap wie andere Objekte:

Der Heap ist der Laufzeitdatenbereich, aus dem Speicher für alle Klasseninstanzen und Arrays zugewiesen wird.

Das Feld wird initialisiert (wenn die Deklaration eine Initialisierung enthält), wenn die Klasse geladen wird , was unmittelbar vor dem ersten Auftreten einer der folgenden Bedingungen geschieht:

  • eine Instanz der Klasse wird erstellt.
  • eine von der Klasse deklarierte statische Methode wird aufgerufen.
  • ein von der Klasse deklariertes statisches Feld wird zugewiesen.
  • es wird ein von der Klasse deklariertes statisches Feld verwendet, und das Feld ist keine konstante Variable (§4.12.4).

Der Zugriff auf das statische Feld erfolgt über 2 spezielle JVM-Anweisungen, getstatic und putstatic . Abgesehen von dieser Unterscheidung ähneln statische Felder nicht statischen Feldern.

5
assylias

Dies ist von Sprache zu Sprache sehr unterschiedlich und kann sogar von Plattform zu Plattform sehr unterschiedlich sein ...

Zum Beispiel werden auf der .NET-Seite statische Member mit der übergeordneten EEClass-Definition "verknüpft". Diese kann ein vom Heap zugeteiltesODERa "wherever" zugeordnetes Member sein (die C # specnicht Kein Heap-/Stack-Verhalten, es handelt sich um ein Implementierungsdetail der VM)

5
JerKimball

Es kann Ausnahmen geben, aber für Referenztypen erstellt das new- Schlüsselwort normalerweise ein Objekt in einer internen Datenstruktur namens "Heap". Der Heap wird von der CLR (Common Language Runtime) verwaltet. Dabei spielt es keine Rolle, ob Sie ein statisches Element, ein Instanzmitglied oder eine lokale Variable haben.

Der Unterschied zwischen statischen Mitgliedern und Instanzmitgliedern (diejenigen ohne das Schlüsselwort static) besteht darin, dass statische Mitglieder nur einmal pro Typ (Klasse, Struktur) und Instanzmitglieder einmal pro Instanz (pro Objekt) vorhanden sind.

Nur der Bezug ist statisch oder nicht; Diese Unterscheidung gilt nicht für das referenzierte Objekt (es sei denn, das Objekt ist ein Werttyp). Ein statischer Member, ein Instanz-Member und eine lokale Variable können alle auf dasselbe Objekt verweisen.

Ich bin nur mit C # vertraut, und dies ist mein Verständnis davon:

Dann startet Ihr Programm und lädt alle zugehörigen Assemblys in eine AppDomain . Wenn der Assembler geladen wird, werden alle statischen Konstruktoren einschließlich statischer Felder aufgerufen. Sie werden dort leben, und die einzige Möglichkeit, sie zu entladen, besteht darin, die AppDomain zu entladen.

4
Jens Kloster

Statische Member und Konstanten werden im Heap gespeichert. Im Gegensatz zu Objekten auf Haufen, die eine Speicherbereinigung erhalten können, bleiben statische Member und Konstanten so lange, bis Appdomain abgerissen wird

2
Ashish Gupta

Statische Variablen gehören zur Klasse, nicht zum Objekt, daher befindet sich nur eine bar im Speicher, auch wenn Sie Tausende von Zeitpunkten von Foo initialisieren.

1
Can Geliş

Nach Vorgabe werden statische Variablen in Constant Pool gespeichert. JVM speichert diese Informationen in Permanent Generation.

1
Mikhail

Dies hängt von der Sprache der Sprache oder vom Designer der Sprache ab. Wenn ich über Java spreche, werden statische Member im Methodenbereich der JVM gespeichert, und alle Objekte sind mit ihnen verbunden. Es ist sehr wichtig zu wissen, dass wir auf das statische Datenelement zugreifen können, ohne das Objekt der Klasse zu erstellen. Dies bedeutet, dass die Zuweisung des Speichers zu den statischen Datenelementen nicht von der Erstellung des Objekts davon abhängt Klasse.

1
Jatin Khurana

Normalerweise werden statische Variablen im Datensegment des Programmspeichers gespeichert. Damit wird für jede Klasse, die im laufenden Programm erstellt wird/ist, die statische Variable im Datensegment erstellt und alle anderen Variablen im Codesegment initialisiert .

im Grunde ist es so

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

hier wird ein einzelner Bereich zwischen Instanzen geteilt.

aus wikipedia "Der Datenbereich enthält globale und statische Variablen, die vom Programm verwendet werden
explizit mit einem Wert initialisiert. "

0
Jitendra