Wie viel Speicher verbraucht ein String in Java 8?

Lesezeit: 4 Minuten

Benutzer-Avatar
Scartz

Ich habe in letzter Zeit viel über die Speicherzuweisung für Strings gelesen und kann keine Details finden, wenn es mit Java 8 genauso ist.

Wie viel Speicherplatz möchte ein String "Alexandru Tanasescu" Verwendung in Java 8? Ich verwende die 64bit-Version.

  • Das String-Objekt hält den Wert in der Unterlage char Reihe (final char value[]), Wie ändert sich der Speicherverbrauch je nach Version?

    – Subhrajyoti Majumder

    3. Juli 2015 um 12:36 Uhr


  • mögliches Duplikat von Memory usage of String in Java

    – Thomas Jungblut

    3. Juli 2015 um 12:40 Uhr

Benutzer-Avatar
Jordi Castilla

Java7 oder niedriger

Minimale String-Speichernutzung :

(bytes) = 8 * (int) ((((no chars) * 2) + 45) / 8)

So

80 = 8 * (int) ((((19) * 2) + 45) / 8)

Grundlegendes zur String-Speichernutzung (QUELLE)

Um die obige Berechnung zu verstehen, müssen wir uns zunächst die Felder eines String-Objekts ansehen. Ein String enthält Folgendes:

  • ein char-Array – also ein separates Objekt – das die eigentlichen Zeichen enthält;
  • ein ganzzahliger Offset in das Array, bei dem die Zeichenfolge beginnt;
  • die Länge der Zeichenfolge;
  • ein weiteres int für die zwischengespeicherte Berechnung des Hashcodes.

Das bedeutet, dass selbst wenn die Zeichenfolge keine Zeichen enthält, 4 Bytes für die char-Array-Referenz plus 3*4=12 Bytes für die drei Int-Felder plus 8 Bytes Objektheader erforderlich sind. Dies ergibt 24 Bytes (was ein Vielfaches von 8 ist, daher werden bisher keine “Padding”-Bytes benötigt).

Dann benötigt das (leere) char-Array weitere 12 Bytes (Arrays haben zusätzliche 4 Bytes, um ihre Länge zu speichern), plus in diesem Fall 4 Bytes zum Auffüllen, um den vom char-Array-Objekt verwendeten Speicher auf ein Vielfaches von zu bringen 16. Insgesamt verwendet also ein leerer String 40 Bytes.

Wenn die String beispielsweise 19 Zeichen enthält, dann benötigt das String-Objekt selbst noch 24 Bytes. Aber jetzt benötigt das char-Array 12 Bytes Header plus 19*2=38 Bytes für die siebzehn Zeichen. Da 12+38=50 kein Vielfaches von 8 ist, müssen wir auch auf das nächste Vielfache von 8 (56) aufrunden. Insgesamt also unser 19-Charakter String verbraucht 56+24 = 80 Bytes.


Java8.

Java 8 hat das nicht offset und length nicht mehr. Nur hash und der CharArray.
@Thomas Jungblut

  • ein char-Array – also ein separates Objekt – das die eigentlichen Zeichen enthält;
  • ein ganzzahliger Offset in das Array, bei dem die Zeichenfolge beginnt;
  • die Länge der Zeichenfolge;
  • ein weiteres int für die zwischengespeicherte Berechnung des Hashcodes.

In Java8 bleibt also die Methode zum Berechnen des Speichers für Strings gleich, aber Sie müssen aufgrund des Fehlens 8 Bytes weniger subtrahieren offset und length.

  • @talex schau mal… ist für java6aber das einzige, was sich in Java8 geändert hat, ist StringPool, die Speichernutzung für Strings bleibt gleich.

    – Jordi Kastilien

    3. Juli 2015 um 12:41 Uhr

  • Java 8 hat den Offset und die Länge nicht mehr. Nur Hash und das Char-Array.

    – Thomas Jungblut

    3. Juli 2015 um 12:43 Uhr

  • Das Offset-Feld in String wurde entfernt, wie @Thomas bemerkt. Siehe zum Beispiel hier.

    – Lii

    3. Juli 2015 um 12:55 Uhr

  • @ThomasJungblut danke … meine Antwort mit neuen Infos aktualisiert … danke für die Infos!!! 🙂

    – Jordi Kastilien

    3. Juli 2015 um 12:56 Uhr


  • @ThomasJungblut AFAIK, diese JVM-Option ist in Java SE 8 nicht mehr verfügbar. Siehe z. B. das folgende JEP für die Gründe: openjdk.java.net/jeps/254

    – Puce

    3. Juli 2015 um 13:31 Uhr

Wenn Sie sich die Oracle Java 8-Quellen ansehen, haben Sie:

EIN char value[] und ein int hash. EIN char ist 2 Bytes und ein int ist 4 Byte.

Also wäre die Antwort nicht yourstring.length * 2 + 4?

Nein. Jedes Objekt hatte Overhead. Ein Array speichert beispielsweise seine Dimensionen. Und sowohl das Array (ein Objekt) als auch der String beanspruchen zusätzlichen Speicher vom Garbage Collector, der Informationen über sie speichert.

Es gibt keinen zuverlässigen Weg, dies zu berechnen, da AFAIK jedes JRE und JDK nicht an die Größe des Objekt-Overheads gebunden ist.

  • Die HotSpot JRE ist die gebräuchlichste und wird fast überall verwendet, außer auf Android-Telefonen. Es hat einen Objektspeicher-Overhead von zwei Wörtern (8 Byte) auf 32-Bit-Systemen. Auf 64-Bit-Systemen ist es komplexer, aber ich denke, Sie erhalten dort auch für mittelgroße Heaps einen 8-Byte-Overhead.

    – Lii

    3. Juli 2015 um 12:48 Uhr


  • @Lii Während die HotSpot JRE wohl die gebräuchlichste ist, kommt die JRE von IBM zB dort zum Einsatz, wo WebSphere zum Einsatz kommt.

    – Puce

    3. Juli 2015 um 12:52 Uhr

  • @Lii OP fragte nach 64-Bit-Computern. (Zugegeben, wenn jemand Android auf einem 64-Bit-Computer ausführt, bezweifle ich die Wahl des Betriebssystems.)

    – Ryan Goldstein

    3. Juli 2015 um 12:59 Uhr

“Alexandru Tanasescu” verwendet 104 Bytes. So kommt man auf die Größe

    long m0 = Runtime.getRuntime().freeMemory();
    String s = new String("Alexandru Tanasescu");
    long m1 = Runtime.getRuntime().freeMemory();
    System.out.println(m0 - m1);

Hinweis: Führen Sie es mit der Option -XX:-UseTLAB aus

  • Hallo, können Sie erklären, wie Java 7 und Java 8 Speicher für “Alexandr Tanasescu” verwenden?

    Benutzer2809386

    25. Februar 2019 um 5:01 Uhr


Gemäß dem folgenden JEP:
http://openjdk.java.net/jeps/254

Die aktuelle Implementierung der String-Klasse speichert Zeichen in einem char-Array und verwendet zwei Bytes (sechzehn Bits) für jedes Zeichen.

In Java SE 9 könnte sich dies ändern.

Beachten Sie jedoch, da dies ein JEP und kein JSR ist (und die Implementierung erwähnt wird), verstehe ich, dass dies implementierungsspezifisch ist und nicht vom JLS definiert wird.

1014450cookie-checkWie viel Speicher verbraucht ein String in Java 8?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy