76

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?

SK98
  • 29
  • 3
Amit
  • 33,847
  • 91
  • 226
  • 299

4 Answers4

71

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.

dsimcha
  • 67,514
  • 53
  • 213
  • 334
  • Could you please also tell me the reason why it takes diff. space on 64-bit and 32-bit systems? – Amit Mar 12 '10 at 05:28
  • 2
    @Yatendra: Pointers have to be big enough to span the entire address space. Therefore, on a 32-bit machine you need 32 bits. On a 64-bit machine you need 64 bits. – dsimcha Mar 12 '10 at 05:29
  • 12
    Not necessarily... there's some interesting work in HotSpot to avoid this: http://wikis.sun.com/display/HotSpotInternals/CompressedOops – Jon Skeet Mar 12 '10 at 06:28
  • 3
    @Jon Skeet: Very interesting, I was not aware of that. I'll rephrase, them: In the absence of JIT optimizations that are extremely clever and not guaranteed, you need 64-bit references if you have 64-bit address space. – dsimcha Mar 12 '10 at 16:06
  • Depending on where is your reference point of scale, the book-keeping overhead isn't small at all. – Pacerier Jan 30 '12 at 10:33
  • @JonSkeet that link is dead now :( – knownasilya Dec 29 '12 at 20:16
  • 1
    @Knownasilya: It's moved to https://wikis.oracle.com/display/HotSpotInternals/CompressedOops – Jon Skeet Dec 29 '12 at 22:02
  • String has more overhead. It is a Object with an char[] array, hashcode cache and more stuff. Depending on Java version (older versions had size+offset, length, hash and chars) and platform this can varry. For Java 7, coop, x64 it is 24 bytes for the String instance and 16 + 2*n for the actual codeunits. So empty string is 40bytes. (empty is not null) – eckes May 12 '15 at 22:50
  • The hashcode cache is only a single copy (per `ClassLoader` of course) and should therefore not be counted as part of the memory demands of `String` instances. – Sayo Oladeji Feb 21 '16 at 14:28
  • 5
    Original links shared by @JonSkeet are dead. Late comers may refer http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html and https://wiki.openjdk.java.net/display/HotSpot/CompressedOops – Thomas Oct 14 '16 at 06:26
  • 1
    That means, In java, null object consumes space on stack only, right? As we know that, the stack contains the reference of the object to heap. Since, null object has nothing to refer. Hence, nothing on heap space. Am i correct? – MrYo Apr 05 '18 at 23:01
14

I'd like to add:

  1. variable of reference type will be initialized as null value.
  2. null is not object. because (null instanceof Object) equals to false
  3. 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

Jacky
  • 8,619
  • 7
  • 36
  • 40
  • 2
    1. *Member* variables of reference type are initialized as null. Local variables aren't. 2. Null is not an `Object`, not because `null instanceof Object` is false, but because null is a reference. 3. There are as many null values in a JVM as have been created by (a) the `aconst_null` opcode (b) member variable initializations (c) etc. The statement doesn't make sense. `null` is always equal to itself, but that doesn't imply anything about identity. – user207421 Feb 09 '17 at 23:05
3

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.)

eckes
  • 10,103
  • 1
  • 59
  • 71
  • A reference is always the size of an object pointer (4 Bytes on compressed or 32bit VMs and 8 Bytes on 64Bit uncompressed). There is no difference between null and other values (only that there is not yet another object referenced in NULL case) – eckes Jun 02 '18 at 21:27
2

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.