I heard a colleague say that I would pay "24 bytes" if I dropped a String member in a Java class, even if the String is empty. Is that accurate? Is it the same for Integer, Float, Double? (as opposed to int, float, double, which would be only 4, 4 and 8 bytes each).
4 Answers
You'll pay 4 or 8 bytes for the reference. Whether you'll pay for an extra object per instance of your "container" object depends on how you get your empty string. For example, if you use the literal ""
then all the instances will refer to the same object, so you'll only need to pay for the reference itself.
If you're creating a separate empty string for each instance, then obviously that will take more memory.

- 1,421,763
- 867
- 9,128
- 9,194
-
So, it is not the case that the reference itself weighs 24 bytes - I think that's what he was suggesting. Phew. I found that too heavy. – Frank Aug 17 '12 at 15:33
-
2@Frank: If he was really suggesting that, I'd be somewhat suspicious of anything else he says... – Jon Skeet Aug 17 '12 at 15:34
-
@Jon Skeet can you please answer this question.... http://stackoverflow.com/questions/11700320/is-string-literal-pool-a-collection-of-references-to-the-string-object-or-a-co – Kumar Vivek Mitra Aug 17 '12 at 15:34
-
2Frank, I doubt he was suggesting what you say because 24 is indeed the number of bytes you pay for a plain, empty instance of `Object` on a typical 64-bit HotSpot. You pay the same amount for an `Integer`. – Marko Topolnik Aug 17 '12 at 15:35
-
1@KumarVivekMitra: You've got an excellent answer there already. – Jon Skeet Aug 17 '12 at 15:35
-
@ Jon i may be really dumb to conclude the answer, i mean whom did the answer prove right, Kathy Sierra or Corey McGlone – Kumar Vivek Mitra Aug 17 '12 at 15:37
-
@KumarVivekMitra: I haven't looked in detail, to be honest - I don't have time right now. – Jon Skeet Aug 17 '12 at 15:39
-
5@KumarVivekMitra Soliciting of this kind is really inappropriate. – Marko Topolnik Aug 17 '12 at 15:40
-
@Marko - so, he was right, just writing "String x" does cost 24 bytes, the 24 bytes of the Object? – Frank Aug 17 '12 at 15:49
-
@Frank: No, for the reasons specified in my answer. – Jon Skeet Aug 17 '12 at 15:50
-
Yes, I'm not getting it. I thought String derived from Object? I've downloaded openjdk's source to get to the bottom of this. There's something I don't understand about "references" and "object instances" – Frank Aug 17 '12 at 15:51
-
1Frank, that's where he **wasn't** right, but I still doubt he meant the reference size. He just confused the declaration with the actual object it will probably refer to---and forgot about Strings being immutable, therefore widely shareable, especially through the constant pool. – Marko Topolnik Aug 17 '12 at 15:52
-
1@Frank: If you're confused between references and objects, I *wouldn't* start delving into the JDK source code. That's going to add to your confusion rather than help you. Read a good Java tutorial which will explain the difference. – Jon Skeet Aug 17 '12 at 16:00
-
Jon - I'm looking at the source... of course, I don't know what the compiler does, but String has 4 private members. I'm going to open another thread to try and understand how the compiler works with refs. – Frank Aug 17 '12 at 16:18
-
@Frank: It's not a matter of how the compiler works with references. It's understanding the difference between references and objects. When your class has a field of type `String`, that field value will *just* be a reference. It's *not* an object. The value could *refer* to an object (or be null), but there could be several other references to the same object too. – Jon Skeet Aug 17 '12 at 19:18
-
Yes, I understand that. I'm used to the C++ model, where if I put something in the declaration of a class, I know the memory layout (more or less) and can even evaluate how many bytes each instance takes (which can be very useful in some environments). – Frank Aug 17 '12 at 19:29
-
@Frank: Right. You need to think differently. Java is not C++, and trying to reason about it as if it *were* C++ will always be painful. The closest you'll come is to think of a `String` field as being *a bit like* a `std:string*` field in C++. – Jon Skeet Aug 17 '12 at 19:36
-
What is best or store null or empty string? – nitinsridar Dec 17 '19 at 08:29
-
@nitinsridar: That entirely depends on the context. It's like asking whether integers are better than floating point numbers or not. – Jon Skeet Dec 17 '19 at 08:42
String is composed out of object header (2 words on HotSpot, 3 on J9), int field and char array reference. Char array itself is composed out of header, int field and the rest of array. Everything is padded to 8 bytes. Usually, chars are encoded with 2 bytes per char. Some JVMs can use alternative encodings for char. At one point J9 could encode strings in UTF8. Modern HotSpot will use 1 byte per char if string is composed of simple chars (essentially 1 byte encoded glyphs of UTF-8, like english alphabet, numbers and such). Otherwise it uses 2 bytes per char for whole array.
So deep size of empty string size is thus:
- 32 bytes on 32 bit HotSpot (16 bytes for String, 16 bytes for char[])
- 56 bytes on 64 bit HotSpot (32 bytes for String, 24 bytes for char[])
- 40 bytes on 64 bit HotSpot with compressed references (24 bytes for String, 16 bytes for char[])
Commonly, empty char array will not be allocated as it's value will be inferred. After all all empty char arrays are equal. So actual penalty for an empty string will be a shallow String size; which is 24 bytes for most common situation today (64 bit HotSpot with compressed ref).
IBM J9 JVM has bigger object header and it will allocate somewhat more.

- 1,087
- 9
- 20
Borrowed from this answer: the program prints 32 bytes for the empty string (and 0 for "" which is in the string pool).
public static void main(String... args) {
long free1 = free();
String s = "";
long free2 = free();
String s2 = new String("");
long free3 = free();
if (free3 == free1) System.err.println("You need to use -XX:-UseTLAB");
System.out.println("\"\" took " + (free1 - free2) + " bytes and new String(\"\") took " + (free2
- free3) + " bytes.");
}
private static long free() {
return Runtime.getRuntime().freeMemory();
}
-
1the empty char array of new String("") is shared. new String("X") results in 72 bytes. – R.Moeller May 16 '15 at 08:08
-
@R.Moeller That's a good point - but I'm pretty sure that the empty string will *always* be in the string pool, even if you don't use it explicitly (it's probably used in many instances across the JDK internal code)... So it depends on what you want to measure. – assylias May 16 '15 at 08:25
-
I think its the zero length char array which is shared .. so new String("") creates a new string but does not create a char array. so 24 bytes is length of empty String, but length of 1-length String is > 72 bytes – R.Moeller May 17 '15 at 15:22
It's true that you'll pay much more for an Integer than for an int. I remember checking a couple Java versions back and the Integer took about 24 bytes more. As long as you've got the String pointing at a null object (aka at nothing) you're only keeping a pointer in memory and I don't think the JVM will preserve a location to initialize it in which case you're not wasting 24 bytes, just 8. If you create the string though (even the empty string "") then you already have an object in memory, and since all objects inherit Object they come with some baggage and take up more memory than you intuitively expect. Depending on your use of the string a common solution is to start with a null object and lazy initialize it when you need it.

- 731
- 5
- 14
-
170 bytes is way, way off. You pay for the reference (typically only 4 bytes---even Steven so far) and 24 bytes for the object on the heap. – Marko Topolnik Aug 17 '12 at 15:36
-
That makes more sense, I mostly remembered the Integer taking up so much more that I reimplemented LinkedList with int. – Shrewd Aug 18 '12 at 05:18
-
Yes, `LinkedList` is a known memory hog. `ArrayList` is much better in that respect. – Marko Topolnik Aug 18 '12 at 07:36