Java-Objektspeicher-Footprint - Visualvm- und java.sizeOf-Messung

8

Ich versuche zu verstehen, was der Speicherabdruck eines Objekts in Java ist. Ich lese dies und andere Dokumente zu Objekt und Speicher in Java.

Wenn ich jedoch die Größe der Java-Bibliothek oder visualvm verwende, erhalte ich zwei verschiedene Ergebnisse, bei denen keiner von ihnen etwas hat, was ich könnte gemäß der vorherigen Referenz ( Ссылка ) erwarten.

Für meinen Test verwende ich Java SE 7 Developer Preview auf einem 64-bits Mac mit java.sizeof 0.2.1 und visualvm 1.3.5 .

Ich habe drei Klassen, TestObject , TestObject2 , TestObject3 .

%Vor%

Meine Hauptklasse:

%Vor%

Mit java.SizeOf () bekomme ich:

%Vor%

Mit Visualvm habe ich:

%Vor%

Laut Dokumentation habe ich über das Internet gelesen, da ich in 64-Bit bin, sollte ich einen Objektkopf von 16 Bytes haben, ok für TestObject .

Dann für TestObject2 Ich sollte 4 Bytes für das Integer-Feld addieren, das die 20 Bytes angibt, ich sollte noch einmal 4 Bytes Padding hinzufügen, was eine Gesamtgröße von 24 Bytes für TestObject2 ergibt. Liege ich falsch?

Wenn ich diesen Weg für TestObject3 fortsetze, muss ich 8 Bytes mehr für die zwei ganzzahligen Felder hinzufügen, was 32 Bytes ergeben sollte.

VisualVm scheint das Padding zu ignorieren, während java.sizeOf 4 Bytes zu verpassen scheint, als wären sie im Objektheader enthalten. Ich kann eine ganze Zahl durch 4 booleans ersetzen, es gibt das gleiche Ergebnis.

Fragen:

Warum geben diese beiden Tools unterschiedliche Ergebnisse?

Sollten wir Polsterung haben?

Ich habe auch irgendwo gelesen (ich habe den Link nicht gefunden), dass es zwischen einer Klasse und ihrer Unterklasse einige Lücken geben könnte, ist es richtig? In diesem Fall könnte eine geerbte Klassenstruktur einen gewissen Speicheraufwand haben?

Gibt es schließlich eine Java-Spezifikation / -Dokument, die Details zu Java enthält?

Danke für Ihre Hilfe.

Aktualisierung:

Um den Kommentar von utapyngo zu beantworten, um die Größe der Objekte in Visualvm zu erhalten, erstelle ich einen Heapdump, dann im Teil "Classes" überprüfe ich die Spalte "size" als nächstes nach der Spalte "instances". Die Anzahl der Instanzen, wenn 1 für jede Art von Objekten vorhanden ist.

Um einen Kommentar von Nathaniel Ford zu beantworten, initiierte ich jedes Fieds und machte dann eine einfache Summe mit ihnen in meiner main Methode, um sie zu nutzen. Es hat die Ergebnisse nicht verändert.

    
Aurélien 19.03.2013, 02:32
quelle

1 Antwort

2

Ja, das Auffüllen kann passieren. Es ist auch möglich, Objekte auf dem Stapel vollständig zu optimieren. Nur die JVM kennt die genauen Größen zu jedem Zeitpunkt. Da solche Techniken, um die Größe aus der Java-Sprache zu approximieren, alle dazu neigen, nicht zuzustimmen, tendieren Tools, die an die JVM anhängen, dazu, die genauesten zu sein. Die drei wichtigsten Techniken zur Implementierung von sizeOf in Java, die mir bekannt sind, sind:

  1. serialisiert das Objekt und gibt die Länge dieser Bytes zurück (eindeutig falsch, aber nützlich für relative Vergleiche)
  2. Listenelement Reflexion, und fest codierte Größenkonstanten für jedes auf einem Objekt gefundene Feld. kann abgestimmt sein, um etwas genau zu sein, aber ändert sich in der JVM und Padding dass die JVM es tun kann oder nicht, wird es werfen.
  3. Listenelement erstellt Lasten von Objekten, führen Sie gc aus und vergleichen Sie die Änderungen in der jvm-Heap-Größe

Keine dieser Techniken ist genau.

Wenn Sie mit der Oracle JVM arbeiten, am oder nach Version 1.5. Dann gibt es eine Möglichkeit, die Größe eines Objekts direkt aus der von der Java-Laufzeitumgebung verwendeten C-Struktur zu lesen. Keine gute Idee für die Produktion, und es falsch machen, dann können Sie die JVM zum Absturz bringen. Aber hier ist ein Blog-Beitrag, den Sie vielleicht interessant finden, wenn Sie es ausprobieren möchten: Ссылка

Was die Dokumentation betrifft, was Java tatsächlich macht, ist das JVM-spezifisch, versionsspezifisch und möglicherweise auch konfigurationsspezifisch. Jede Implementierung kann Objekte unterschiedlich handhaben. Selbst in dem Ausmaß, in dem Objekte vollständig optimiert werden, können beispielsweise Objekte, die nicht aus dem Stapel ausgegeben werden, frei auf dem Heap nicht zugewiesen werden. Einige JVMs können es sogar schaffen, das Objekt vollständig in den CPU-Registern zu halten. Nicht Ihr Fall hier, aber ich schließe es als ein Beispiel an, warum es schwierig ist, die wahre Größe von Java-Objekten zu bekommen.

Also nehmen Sie am besten alle Größenwerte, die Sie mit einer Prise Salz bekommen, und behandeln Sie sie nur als "Richtwertmessung".

    
Chris K 19.03.2013 08:28
quelle

Tags und Links