51

I read a lot about memory allocation for Strings lately and can't find any details if things are the same with Java 8.

How much memory space would a String like "Alexandru Tanasescu" use in Java 8? I use the 64bit version.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Scartz
  • 513
  • 1
  • 4
  • 5
  • String object holds value in underlaying `char` array(`final char value[]`), How does that change memory consumption on depending upon different version ? – Subhrajyoti Majumder Jul 03 '15 at 12:36
  • possible duplicate of [Memory usage of String in Java](http://stackoverflow.com/questions/19776463/memory-usage-of-string-in-java) – Thomas Jungblut Jul 03 '15 at 12:40

4 Answers4

58

Java7 or lower

Minimum String memory usage :

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

So

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

Understanding String memory usage (SOURCE)

To understand the above calculation, we need to start by looking at the fields on a String object. A String contains the following:

  • a char array— thus a separate object— containing the actual characters;
  • an integer offset into the array at which the string starts;
  • the length of the string;
  • another int for the cached calculation of the hash code.

This means even if the string contains no characters, it will require 4 bytes for the char array reference, plus 3*4=12 bytes for the three int fields, plus 8 bytes of object header. This gives 24 bytes (which is a multiple of 8 so no "padding" bytes are needed so far).

Then, the (empty) char array will require a further 12 bytes (arrays have an extra 4 bytes to store their length), plus in this case 4 bytes of padding to bring the memory used by the char array object up to a multiple of 16. So in total, an empty string uses 40 bytes.

If the String contains, say, 19 characters, then the String object itself still requires 24 bytes. But now the char array requires 12 bytes of header plus 19*2=38 bytes for the seventeen chars. Since 12+38=50 isn't a multiple of 8, we also need to round up to the next multiple of 8 (56). So overall, our 19-character String will use up 56+24 = 80 bytes.


Java8.

Java 8 does not have the offset and length anymore. Only hash and the CharArray.
@Thomas Jungblut

  • a char array— thus a separate object— containing the actual characters;
  • an integer offset into the array at which the string starts;
  • the length of the string;
  • another int for the cached calculation of the hash code.

So, in Java8 the way to calculate memory for strings remains same but you must subtract 8 bytes less due to the missing offset and length.

user2555595
  • 182
  • 1
  • 4
  • 18
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • 1
    @talex take a look... is for `java6`, but the only thing changed in Java8 is StringPool, memory usage for `Strings` remains same. – Jordi Castilla Jul 03 '15 at 12:41
  • 6
    Java 8 does not have the offset and length anymore. Only hash and the char array. – Thomas Jungblut Jul 03 '15 at 12:43
  • The offset field in `String` has been removed as @Thomas notes. See for example [here](http://java-performance.info/changes-to-string-java-1-7-0_06/). – Lii Jul 03 '15 at 12:55
  • @ThomasJungblut thanks... updated my answer with new info... thanks for the info!!! :) – Jordi Castilla Jul 03 '15 at 12:56
  • Also important to mention is `-XX:+UseCompressedStrings` which can save 2x bytes per char in the string. – Thomas Jungblut Jul 03 '15 at 12:59
  • @JordiCastilla: That's great! But I think it is better to edit your original text than to add a correction on the end. Also, the blog I link to in my comment states that the change was made in Java 1.7.0_06, not in Java 8, so it has been around a while already. – Lii Jul 03 '15 at 12:59
  • 1
    @ThomasJungblut AFAIK, this JVM option is not available anymore in Java SE 8. E.g. see the following JEP for the reasons: http://openjdk.java.net/jeps/254 – Puce Jul 03 '15 at 13:31
  • another int for the cached calculation of the hash code.? what it supposed to mean? – Hari Krishnan Aug 08 '17 at 20:05
  • "*subtract 8 bytes less*" means that it takes 8 bytes more. – user1803551 Oct 08 '18 at 15:02
10

"Alexandru Tanasescu" uses 104 bytes. This is how to get the size

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

Note: run it with -XX:-UseTLAB option

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • 1
    hi, can you explain how java 7 and java 8 use memory for "Alexandr Tanasescu" ? –  Feb 25 '19 at 05:01
8

If you look at the Oracle Java 8 sources, you have:

A char value[] and an int hash. A char is 2 bytes, and an int is 4 bytes.

So wouldn't the answer be yourstring.length * 2 + 4?

No. Every object had overhead. An array stores its dimensions, for example. And both the array (an object) and the string will incur extra memory from the garbage collector storing information about them.

There is no reliable way to calculate this, because AFAIK each JRE and JDK has no obligation to the size of object overhead.

Ryan Goldstein
  • 523
  • 3
  • 14
  • The HotSpot JRE is the most common one and it is used almost everywhere except on Android phones. It has a two word (8 byte) object memory overhead on 32 bit systems. On 64 bit systems it is more complex, but I think you get a 8 byte overhead there also for moderately sized heaps. – Lii Jul 03 '15 at 12:48
  • @Lii While the HotSpot JRE is probably the most common one, the JRE from IBM e.g. is used where WebSphere is used. – Puce Jul 03 '15 at 12:52
  • @Lii OP asked for 64bit computers. (Granted, if anyone is running Android on a 64bit computer, I question their choice of OS.) – Ryan Goldstein Jul 03 '15 at 12:59
0

According to the following JEP: http://openjdk.java.net/jeps/254

The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character.

In Java SE 9 this might change.

Note however, since this is a JEP not a JSR (and it mentions implementation), I understand, that this is implementations specific and not defined by the JLS.

Puce
  • 37,247
  • 13
  • 80
  • 152