103

As I understand, in Java, stack memory holds primitives and method invocations and heap memory is used to store objects.

Suppose I have a class

class A {
       int a ;
       String b;
       //getters and setters
}
  1. Where will the primitive a in class A be stored?

  2. Why does heap memory exist at all? Why can't we store everything on the stack?

  3. When the object gets garbage collected, is the stack associated with the objected destroyed?

4
  • 1
    stackoverflow.com/questions/1056444/is-it-on-the-stack-or-heap seems to answer your question.
    – S.Lott
    Commented Apr 5, 2011 at 11:48
  • @S.Lott, except that this one is about Java, not C. Commented Apr 5, 2011 at 11:51
  • @Péter Török: Agreed. While the code sample is Java, there's no tag to indicate that it's only Java. And the general principle ought to apply as well to Java as C. Further, there's a lot of answers to this question on Stack Overflow.
    – S.Lott
    Commented Apr 5, 2011 at 11:54
  • 9
    @SteveHaigh: on this site, everyone is way too concerned about whether something belongs here... I wonder what mindshare this site is really getting with all the nit-pickiness about whether questions belong here or not. Commented Jan 16, 2014 at 22:29

6 Answers 6

109

The basic difference between stack and heap is the life cycle of the values.

Stack values only exist within the scope of the function they are created in. Once it returns, they are discarded.
Heap values however exist on the heap. They are created at some point in time, and destructed at another (either by GC or manually, depending on the language/runtime).

Now Java only stores primitives on the stack. This keeps the stack small and helps keeping individual stack frames small, thus allowing more nested calls.
Objects are created on the heap, and only references (which in turn are primitives) are passed around on the stack.

So if you create an object, it is put on the heap, with all the variables that belong to it, so that it can persist after the function call returns.

13
  • 3
    "and only references (which in turn are primitives) " Why do say that references are primitives ? Can you clarify please?
    – Geek
    Commented Jul 31, 2012 at 8:33
  • 5
    @Geek: Because the common definition of primitive data types applies: "a data type provided by a programming language as a basic building block". You might also notice that references are listed among the canonical examples further down in the article.
    – back2dos
    Commented Jul 31, 2012 at 8:52
  • 4
    @Geek: In terms of data, you may view any of the primitive data types - including references - as numbers. Even chars are numbers and can be used interchangeably as so. References are also just numbers referring to a memory address, either 32 or 64 bits long (although they cannot be used as such - unless you're messing around with sun.misc.Unsafe). Commented Apr 2, 2013 at 9:35
  • 5
    The terminology of this Answer is wrong. According to the Java Language Specification, references are NOT primitives. The gist of what the Answer says is correct though. (While you can make an argument that references are "in a sense" primitive is by the by. The JLS defines the terminology for Java, and it says that the primitive types are boolean, byte, short, char, int, long, float and double.)
    – Stephen C
    Commented Nov 22, 2014 at 22:42
  • 4
    As I found in this article, Java may store objects on the stack (or even in registers for small short lived objects). The JVM can do quite a bit under the covers. Its not exactly correct to say "Now Java only stores primitives on the stack."
    – user40980
    Commented Nov 22, 2014 at 23:45
54

Where are primitive fields stored?

Primitive fields are stored as part of the object that is instantiated somewhere. The easiest way to think of where this is - is the heap. However, this is not always the case. As described in Java theory and practice: Urban performance legends, revisited:

JVMs can use a technique called escape analysis, by which they can tell that certain objects remain confined to a single thread for their entire lifetime, and that lifetime is bounded by the lifetime of a given stack frame. Such objects can be safely allocated on the stack instead of the heap. Even better, for small objects, the JVM can optimize away the allocation entirely and simply hoist the object's fields into registers.

Thus, beyond saying "the object is created and the field is there too", one cannot say if something is on the heap or on the stack. Note that for small, short-lived objects, it's possible that the 'object' won't exist in memory as such and may instead have its fields placed directly in registers.

The paper concludes with:

JVMs are surprisingly good at figuring out things that we used to assume only the developer could know. By letting the JVM choose between stack allocation and heap allocation on a case-by-case basis, we can get the performance benefits of stack allocation without making the programmer agonize over whether to allocate on the stack or on the heap.

Thus, if you have code that looks like:

void foo(int arg) {
    Bar qux = new Bar(arg);
    ...
}

where the ... doesn't allow qux to leave that scope, qux may be allocated on the stack instead. This is actually a win for the VM because it means it doesn't need to ever be garbage collected - it will disappear when it leaves the scope.

More on escape analysis at Wikipedia. For those willing to delve into papers, Escape Analysis for Java from IBM. For those coming from a C# world, you may find The Stack Is An Implementation Detail and The Truth About Value Types by Eric Lippert good reads (they're useful for Java types also, as many of the concepts and aspects are the same or similar). Why do .Net books talk about stack vs heap memory allocation? also goes into this.

On the whys of the stack and the heap

On the heap

So, why have the stack or the heap at all? For things that leave scope, the stack can be expensive. Consider the code:

void foo(String arg) {
    bar(arg);
    ...
}

void bar(String arg) {
    qux(arg);
    ...
}

void qux(String arg) {
    ...
}

The parameters are part of the stack too. In the situation that you don't have a heap, you would be passing the full set of values on the stack. This is fine for "foo" and small strings... but what would happen if someone put a huge XML file in that string? Each call would copy the entire huge string onto the stack - and that would be quite wasteful.

Instead, it is better to put the objects that have some life outside of the immediate scope (passed to another scope, stuck in a structure that someone else is maintaining, etc...) into another area which is called the heap.

On the stack

You don't need the stack. One could, hypothetically, write a language that doesn't use a stack (of arbitrary depth). An old BASIC that I learned on in my youth did so, one could only do 8 levels of gosub calls and all variables were global - there was no stack.

The advantage of the stack is that when you have a variable that exists with a scope, when you leave that scope, that stack frame is popped. It really simplifies what is there and what isn't. The program moves to another procedure, a new stack frame; the program returns to the procedure, and you've back in the one that sees your current scope; the program leaves the procedure and all the items on the stack are deallocated.

This really makes life easy for the person writing the runtime for the code to use a stack and a heap. There are simply many concepts and ways of working on the code, allowing the person writing the code in the language to be freed of thinking of them explicitly.

The stack's nature also means it can't become fragmented. Memory fragmentation is a real problem with the heap. You allocate a few objects, then garbage collect a middle one, and then try finding space for the next large one to be allocated. It's a mess. Being able to put things on the stack instead means that you don't have to deal with that.

When something is garbage collected

When something is garbage collected, it's gone. But it is only garbage collected because it's already forgotten about - there are no more references to the object in the program that can be accessed from the current state of the program.

I'll point out that this is a very large simplification of garbage collection. There are many garbage collectors - even within Java, you can tweak the garbage collector by using various flags (docs). These behave differently and the nuances of how each one does things is a bit too deep for this answer. You may wish to read Java Garbage Collection Basics to get a better idea of how some of that works.

That said, if something is allocated on the stack, it is not garbage collected as part of System.gc() - it is deallocated when the stack frame pops. If something is on the heap, and referenced from something on the stack, it will not be garbage collected at that time.

Why does this matter?

For the most part, it's tradition. The text books written and compiler classes and various bits documentation make a big deal about the heap and the stack.

However, virtual machines of today (JVM and similar) have gone to great lengths to try to keep this hidden from the programmer. Unless you are running out of one or the other and need to know why (rather than just increasing the storage space appropriately), it doesn't matter too much.

The object is somewhere and it's in the place where it can be accessed correctly and quickly for the appropriate amount of time that it exists. Whether it's on the stack or the heap - it doesn't really matter.

0
7
  1. In the heap, as part of the object, which is referenced by a pointer in the stack. ie. a and b will be stored adjacent to each other.
  2. Because if all memory were stack memory, it wouldn't be efficient any more. It's good to have a small, fast-access area where we start and have that reference items in the much larger area of memory which remains. However, this is overkill when an object is simply a single primitive which would take up about the same amount of space on the stack as the pointer to it would.
  3. Yes.
3
  • 1
    I would add to your point #2 that if you stored objects on the stack (imagine a dictionary object with hundreds of thousands of entries) then in order to pass it to or return it from a function you'd need to copy the object every time. By using a pointer or reference to an object in the heap, we only pass the (small) reference. Commented Apr 5, 2011 at 12:25
  • 1
    I thought 3 would be 'no' because if the object is being garbage-collected, then there is no reference in the stack pointing to it.
    – Luciano
    Commented Apr 5, 2011 at 13:19
  • @Luciano - I see your point. I read question 3 differently. The "at the same time" or "by that time" is implicit. :: shrug ::
    – pdr
    Commented Apr 5, 2011 at 16:53
3
  1. On the heap unless Java allocates the class instance on the stack as an optimization after proving via escape analysis that this will not affect semantics. This is an implementation detail, though, so for all practical purposes except micro-optimization the answer is "on the heap".

  2. Stack memory must be allocated and deallocated in last in first out order. Heap memory can be allocated and deallocated in any order.

  3. When the object is garbage collected, there are no more references pointing to it from the stack. If there were, they'd keep the object alive. Stack primitives aren't garbage collected at all because they're automatically destroyed when the function returns.

3

Stack memory is used to store local variables and function call.

While heap memory is used to store objects in Java. No matter, where object is created in code.

Where will the primitive a in class A be stored?

In this case primitive a is associated with class A object. So it creates in Heap Memory.

Why does heap memory exist at all? Why can't we store everything on the stack?

  • Variables created on the stack will go out of scope and automatically destroyed.
  • Stack is much faster to allocate in comparison to variables on the heap.
  • Variables on the heap must be destroyed by Garbage Collector.
  • Slower to allocate in comparison to variables on the stack.
  • You would use the stack if you know exactly how much data you need to allocate before compile time and it is not too big.( primitive local variables store in stack)
  • You would use the heap if you don't know exactly how much data you will need at runtime or if you need to allocate a lot of data.

When the object gets garbage collected, is the stack associated with the objected destroyed?

Garbage Collector works under the scope of Heap memory, so it destroys objects which are not having reference chain from to root.

-1

For better understanding (Heap/Stack memory):

Heap/Stack memory image

Not the answer you're looking for? Browse other questions tagged or ask your own question.