.NET hinter den Kulissen: Was speichert 'Objekt'?

8

Ein naives Typsystem würde Objekte als Zeiger auf seinen Typ speichern (der viele nützliche Informationen enthält, wie eine V-Tabelle, Objektgröße usw.), gefolgt von seinen Daten. Wenn .Net ein solches Typsystem hätte, würde ein object bei einem 32-Bit-System 4 Bytes und bei 64-Bit 8 Bytes belegen.

Wir können sehen, dass es nicht ist >. Der Objekt-Overhead besteht aus zwei Zeigergrößen, außerdem gibt es eine "minimale" Größe von einer weiteren Zeigergröße.

Also, was speichert object tatsächlich hinter den Kulissen?

    
configurator 06.04.2011, 03:06
quelle

2 Antworten

7

Ja, so sieht es aus. Der 'Typ-Handle', auch 'Methodentabellenzeiger' genannt, ist bei Offset 0, die Objektdaten folgen bei Offset 4. Bei Offset-4 gibt es ein zusätzliches Feld namens 'Syncblock'. Es ist dort, weil es auch an dem Garbage-Collected-Heap teilnimmt, wenn der Objektraum nicht verwendet wird, eine doppelt verknüpfte Liste von freien Blöcken, die zwei Zeiger benötigt. Damit es nicht verschwendet wird, hat der Syncblock mehrere Verwendungsmöglichkeiten, wie Speichern des Sperrzustands, Speichern des Hash-Codes, Speichern eines Zeigers auf einen expliziten Syncblock, wenn zu viel gespeichert werden muss.

Das kleinstmögliche Objekt ist für ein Box-Byte, 4 + 4 + 1 = 9 Bytes. Die Zuordnungsgranularität für den GC-Heap beträgt jedoch 4 Byte, sodass Sie das nächste Vielfache von 4, 12 Byte erhalten.

Dies ist alles gut sichtbar mit dem Debugger in Visual Studio. Sie finden Hinweise in diese Antwort .

    
Hans Passant 06.04.2011, 03:17
quelle
5

(Dies ist alles aus der Microsoft Shared Source CLI ; es enthält den Quellcode der CLR.

Wenn Sie sich clr\src\vm\object.h ansehen, sehen Sie:

%Vor%

was ziemlich selbsterklärend ist. Außerdem können Sie in clr\src\vm\gcscan.cpp Anweisungen wie

sehen %Vor%

oder

%Vor%

was erklärt, warum Sie die unerwarteten Objektgrößen sehen. :)

Aktualisierung:

@Hans hatte einen großen Punkt auf dem Sync-Block; Ich möchte nur auf eine Subtilität hinweisen, die wiederum in object.h dokumentiert ist:

%Vor%

Beachten Sie diesen Teil:

  

Der Sync-Block-Index befindet sich tatsächlich bei einem negativen Offset für die Instanz.

Also folgt der Sync-Block scheinbar nicht der Methodentabelle (wie Hans schon erwähnt hat), aber es kommt vor - es ist also kein "normales" Teil des Objekts (für das Fehlen eines besseren Wortes).

    
Mehrdad 06.04.2011 03:08
quelle

Tags und Links