@S.Lott, except that this one is about Java, not C.
–
Péter TörökApr 5 '11 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.LottApr 5 '11 at 11:54

3

@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.
–
Sam GoldbergJan 16 '14 at 22:29

5 Answers
5

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.

@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).
–
Sune RasmussenApr 2 '13 at 9:35

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 CNov 22 '14 at 22:42

1

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."
–
MichaelTNov 22 '14 at 23:45

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, its 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, quxmay 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.

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 there. 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. They 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. Its 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, its gone. But it is only garbage collected because its 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, its 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 its in the place where it can be accessed correctly and quickly for the appropriate amount of time that it exists. If its on the stack or the heap - it doesn't really matter.

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.

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.

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.
–
Scott WhitlockApr 5 '11 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.
–
LucianoApr 5 '11 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 ::
–
pdrApr 5 '11 at 16:53

In case of Java, the only variables that go on stack are the local variables being used by the current method invocation. Of course only in case of primitive types their value is going to be actually stored on stack.

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

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

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.