Java - Does null variable require space in memory
Consider the following block of code:
class CheckStore {
private String displayText;
private boolean state;
private String meaningfulText;
private URL url;
public CheckStore(String text, boolean state) {
this.displayText = text;
this.state = state;
}
:
:
}
When I initialize two variables (displayText
and state
) in the constructor, do the other two variables (meaningfulText
and url
) require space in the memory to store null
value?
Q1. If they do require space, how much memory does a null
value take in the memory?
(ex. int
takes 4 bytes).
Q2. How much space does a string take in memory? How much memory space does a string take? Does it depend on the length of the string?
In Java, null
is just a value that a reference (which is basically a restricted pointer) can have. It means that the reference refers to nothing. In this case you still consume the space for the reference. This is 4 bytes on 32-bit systems or 8 bytes on 64-bit systems. However, you're not consuming any space for the class that the reference points to until you actually allocate an instance of that class to point the reference at.
Edit: As far as the String, a String
in Java takes 16 bits (2 bytes) for each character, plus a small amount of book-keeping overhead, which is probably undocumented and implementation specific.
I'd like to add:
- variable of reference type will be initialized as null value.
- null is not object. because (null instanceof Object) equals to false
-
there is only one null value in JVM. No matter how many variables refer to null.
Object s = (String)null;
Object i = (Integer)null;
System.out.println(s == i);//true
You can use jol to get the layout of that class. (However be careful, you might need a deeper understanding on the mechanics behind it, don't blindly trust the result and be aware it is just an estimate for the currently used VM (1.7.0_76 x64 win in my case:):
I use the CLI version I guess the proper method would be to include the library in your project, but anyway, it seems to work this way:
test>java -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
Running 64-bit HotSpot VM.
Using compressed oop with 0-bit shift.
Using compressed klass with 0-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
VM fails to invoke the default constructor, falling back to class-only introspection.
test.CheckStore object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 1 boolean CheckStore.state N/A
13 3 (alignment/padding gap) N/A
16 4 String CheckStore.displayText N/A
20 4 String CheckStore.meaningfulText N/A
24 4 URL CheckStore.url N/A
28 4 (loss due to the next object alignment)
Instance size: 32 bytes (estimated, the sample instance is not available)
Space losses: 3 bytes internal + 4 bytes external = 7 bytes total
and the same with automatic compressed oops off:
test>java -XX:-UseCompressedOops -cp target\classes;jol-cli-0.3.1-full.jar org.openjdk.jol.Main internals test.CheckStore
Running 64-bit HotSpot VM.
Objects are 8 bytes aligned.
Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
VM fails to invoke the default constructor, falling back to class-only introspection.
test.CheckStore object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 16 (object header) N/A
16 1 boolean CheckStore.state N/A
17 7 (alignment/padding gap) N/A
24 8 String CheckStore.displayText N/A
32 8 String CheckStore.meaningfulText N/A
40 8 URL CheckStore.url N/A
Instance size: 48 bytes (estimated, the sample instance is not available)
Space losses: 7 bytes internal + 0 bytes external = 7 bytes total
Those are only the layouts for the object itself if your fields are null, then it will not point to more objects, otherwise you have to look at the target types (URL
and String
) as well. (And if you have multiple instances of all of them it depends if you use the same multiple times or different ones). An null field cannot be skipped in memory, as it would require the instance to be resized when it is assigned. So the fields are all pre-constructed, they just do not reference allocated objects somewhere else on the heap.
NB: you get some more details if you implement a default constructor, but the sizing in this specific case would be the same. In case you wonder where the sequence and padding of fields is coming from, you can check this article - (basically it aligns objects on 8 bytes, sorts fields by size, groups same type together, references last. Fields from super types are first, 4 byte aligned.)
Null means 0. There is usually one place null defined in memory. Whenever one points to it using a programming language. Everything points to same place. It means only one 4 byte memory is consumed for NULL. Then whatever points to it does not consume any more memory. Definition of NULL is language specific but defining it void *ptr=0; is common in C and C++. JAVA must have defined it similarly. It is not possible to point to nothing ofc. You have to point to something. But we define a common nothing and everything points to it consume only that space.