14

I have this class :

public class Stack {

   private class Node {
       String item;
       Node next;
   }
   // some other methods here

}

In my book, the author says that the size per stack Node is 40 bytes including:

16 bytes (object overhead)
8 bytes (inner class extra overhead)
8 bytes (references to string)
8 bytes (references to node)
----------------------------------------------
40 bytes per stack node

I understand that the last two things refer to the size of the references to the String and Node. But I don't know what the object overhead and inner class extra overhead correspond to. Can you please explain?

Sai Ye Yan Naing Aye
  • 6,622
  • 12
  • 47
  • 65
hqt
  • 29,632
  • 51
  • 171
  • 250

8 Answers8

6

object overhead

Every object has a header which is typically 8-12 bytes long. Each object is also 8 byte aligned and a simple estimate is you say its about 16 bytes long.

inner class extra overhead

As your inner class is not static, it has a reference to the outer class.

If this were an anonymous inner class you might have copies of any number of final variables (any used in the anonymous class code)

8 bytes (inner class extra overhead) 8 bytes (references to string) 8 bytes (references to node)

Most JVMs use 32-bit references so the size would be 4 bytes. Even 64-bit JVM with a heap up to 32 GB can use 32-bit references.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • `Even 64-bit JVM with a heap up to 32 GB can use 32-bit references.` How come? they can split the heap for 32bit addressing and 64? – Lukasz Madon Aug 30 '12 at 13:52
  • 1
    For small heaps the 32-bit reference is relative to the start of the heap, for medium heaps, the reference is multiplied by 8 (as each object is on an 8 byte boundary) and for heaps between 26-31 GB, it is multiplied by 8 and offset. For heaps 32 GB and larger, 64-bit references are used. – Peter Lawrey Aug 30 '12 at 13:55
  • 1
    @Lukas: [Compressed object pointers](http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html#compressedOop) are a feature of the Oracle Hotspot VM. Other JVMs may have similar optimizations. – meriton Sep 03 '12 at 18:09
  • 1
    OpenJDK, JRockit and IBM'S JVM has them as well. https://wikis.oracle.com/display/HotSpotInternals/CompressedOops http://www.ibm.com/developerworks/java/library/j-codetoheap/ https://blogs.oracle.com/jrockit/entry/understanding_compressed_refer – Peter Lawrey Sep 03 '12 at 18:12
3

First of all: all the concrete numbers that you quote are very implementation-dependent and can vary a lot based on what JVM you use.

Most JVMs, however, will have similar values (most JVMs use an object header for example).

The object header contains "bookkeeping" information that the JVM needs to keep track of the object. For example it will usually contain something that indicates the exact type of the object.

What you call "inner class extra overhead" probably refers to the fact that every instance of a non-static inner class is "bound" to an instance of the outer class. You can think of it as an implicit field that looks like this: private final Stack Stack_this. In fact, you can actually use that value by referring to Stack.this inside the code of Node. That implcit field will take the same amount of memory as a normal reference variable (which is usually 4 or 8 bytes, depending on your architecture/JVM).

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
2

Here you can find the answer: What is the memory overhead of an object in Java?

And a more detailed answer here:

Object memory usage in Java: http://www.javamex.com/tutorials/memory/object_memory_usage.shtml

Instances of an object on the Java heap don't just take up memory for their actual fields. Inevitably, they also require some "housekeeping" information, such as recording an object's class, ID and status flags such as whether the object is currently reachable, currently synchronization-locked etc.

Community
  • 1
  • 1
ragklaat
  • 926
  • 5
  • 12
2

An inner class has an implicit reference to the outer class, as if it had a Stack outer object that is initialized in the constructor. That reference is what consumes the extra 8 bytes, and it is what allows you to use Stack.this in your inner class. Here is a sample snippet:

public class Stack {
    String item;   // intentionally named the same as the one in the inner class

    private class Node {
        String item; // hides the field in the outer class!
        Node next;

        void doSomething() {
            this.item = null;
            Stack.this.item = null; // << note the reference to the outer instance
        }
    }
}

Note that a static inner class would not incur that overhead, since it doesn't have a pointer to the outer object.

Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
2

Instances of the inner class will be garbage collected according to normal rules (i.e. when they are no longer referenced). However, each instance of the inner class contains a hidden reference to its parent instance of the outer class. This means that if there are any live references to instances of the inner class, they will prevent the associated instances of the outer class from being garbage collected. But it only works in that direction, not the other way around.

Junteng
  • 21
  • 2
1

The exact size of any particular object isn't specifically defined in any of the Java platform specifications

The amount of overhead associated with an object isn't defined, but 8 bytes is typical.

Refer here for more info

drkthng
  • 6,651
  • 7
  • 33
  • 53
perilbrain
  • 7,961
  • 2
  • 27
  • 35
1

First, your values for object references assumes a 64 bit JVM, on a 32 bit JVM, the references use 4 bytes.

The Object overhead is the header of the object which contains information about the object, used by the JVM and is generally 16 bytes.

The inner class over head is due to the fact that the inner class holds a reference to the containing object (the Stack instance).

assylias
  • 321,522
  • 82
  • 660
  • 783
0

I still don't understand how "40 bytes per stack node" means. You know when I create a new Node instance I do not create a new Stack instance. How can I take 16bytes (object overhead) into account when I create a new Node instance? I'm following Algorithm too and I was confuzed here.

dragonfly
  • 33
  • 5