Warum der Overhead beim Zuweisen von Objekten / Arrays in Java?

9

Wie viele Bytes belegt ein Array in Java? Angenommen, es handelt sich um eine 64-Bit-Maschine, und es wird auch angenommen, dass ein Array N Elemente enthält, sodass alle diese Elemente für verschiedene Array-Typen 2 * N, 4 * N oder 8 * N Byte belegen würden.

Und eine Vorlesung in Coursera besagt, dass es 2 * N + 24, 4 * N + 24 oder 8 * N + 24 Bytes für ein N-Element-Array belegen würde und die 24 Bytes als Overhead bezeichnet werden, erklärte aber nicht, warum der Overhead ist erforderlich.

Auch Objekte haben Overheads, dh 16 Bytes.

Was genau sind diese Gemeinkosten? Woraus bestehen diese 24/16 Bytes?

Gibt es diese Gemeinkosten auch nur in Java? Wie wäre es mit C, C ++ und Python?

Gnijuohz
quelle
1
@ Gnijuohz: Wollen Sie fragen: Aus welchen Daten besteht dieser Overhead?
FrustratedWithFormsDesigner
@YannisRizos: Ich denke, das OP möchte wissen, was sich tatsächlich in diesen 24 Bytes für Arrays befindet.
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Ah, das scheint eine bessere Interpretation der Frage zu sein als meine.
Yannis
@YannisRizos Entschuldigung für meine schlechte Einstellung. Aber wenn du diesen Link postest, kann ich nicht anders, als zu denken, dass das eine Art Sarkasmus ist. Zu defensiv, denke ich.
Gnijuohz

Antworten:

16

Jedes Java-Objekt verfügt über einen Header, der für die JVM wichtige Informationen enthält. Das wichtigste ist ein Verweis auf die Klasse des Objekts (ein Maschinenwort), und es gibt einige Flags, die vom Garbage Collector verwendet werden, um die Synchronisation zu verwalten (da jedes Objekt synchronisiert werden kann), die ein anderes Maschinenwort aufnimmt (unter Verwendung von Teilwörtern würde) schlecht für die Leistung sein). Das sind also 2 Wörter, das sind 8 Bytes auf 32-Bit-Systemen und 16 Bytes auf 64-Bit. Arrays benötigen zusätzlich ein int-Feld für die Array-Länge, das weitere 4 Bytes beträgt, möglicherweise 8 auf 64-Bit-Systemen.

Wie für andere Sprachen:

  • C hat keine Objekte, also natürlich keine Objekt-Header - aber möglicherweise einen Header für jedes separat zugewiesene Speicherelement.

  • In C ++ haben Sie keine Garbage Collection und können keine beliebigen Objekte für die Synchronisierung verwenden. Wenn Sie jedoch Klassen mit überschriebenen Methoden haben, hat jedes Objekt einen Zeiger auf seine vtable, genau wie der Verweis des Java-Objekts auf seine Klasse. Wenn Sie intelligente Zeiger verwenden, die die Speicherbereinigung durchführen, benötigen sie Verwaltungsdaten.

  • Ich weiß nichts über Python, aber ich bin mir ziemlich sicher, dass es auch einen Verweis auf die Klasse und Informationen zur Haushaltsführung für den Garbage Collector benötigt.

Michael Borgwardt
quelle
In OpenJDK wird derzeit daran gearbeitet, die Größe der Objekt-Header zu reduzieren, kleine, aber wichtige Schritte :-)
Martijn Verburg
In C ++ benötigen nur polymorphe Klassen vtables. std::pair<int, float>ist eine einfache Klasse, die überhaupt keine vtable benötigt. Infolgedessen kann es sehr gut in 8 Bytes passen. Außerdem müssen intelligente Zeiger keine zusätzliche Haushaltsführung hinzufügen. Ein klares Gegenbeispiel ist std::unique_ptr<T>, dass es normalerweise genauso groß ist wie das Raw T*(unique_ptr macht natürlich keine GC).
MSalters
4
C hat auch einen Overhead. Jeder malloczugewiesene Speicherblock benötigt einen Header, der freedann verwendet wird.
Herby
Mindestens eine mir bekannte Malloc-Bibliothek verwendet einen 8-Byte-Header auf 32-Bit-Systemen (dies ist eine 4-Byte-Länge, die in zwei Sätze von 2-Byte-Sentinel-Werten, IIRC, eingeklammert ist).
Donal Fellows