Stack and Heap memory in Java

  • 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?

    @S.Lott, except that this one is about Java, not C.

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

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

  • back2dos

    back2dos Correct answer

    10 years ago

    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.

    "and only references (which in turn are primitives) " Why do say that references are primitives ? Can you clarify please?

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

    @Geek: In terms of data, you may view any of the primitive data types - including references - as numbers. Even `char`s 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`).

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

    Reference: docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.2

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

    You are right of course. Half a year before this answer I made the same point about C#. This question however seems to ask for a basic mental model to understand the different roles of the heap and the stack, and to that end I think simplicity beats accuracy ;)

    Yes... but the simplest answer is 'it doesn't really matter - stop worrying and love the vm.' Trying for simplicity without accuracy may perpetuate the myths that are out there about performance and how things (don't) work. I'd contend the classic simple model is *more* complex than the modern simple model of "its where it is fastest to access and the compiler is smarter than you."

    Some Java runtimes are not JITted, particularly embedded ones, where performance does matter a lot more, in which case the answer you propose can be downright detrimental. The simplest answer to performance is "love thy profiler" and nothing else. Still, this question is **not about performance** and nowhere did I make any claims on performance. I think the understanding of heap and stack should be acquired, before it can be transcended. This question is about scope and life cycle and for that I think the model is suitable.

    If I say `int[] s = new int[]{1,2,3,4}` you are saying that it will still be created in stack? I thought as soon as we use `new`, we are asking the compiler to allocate memory in heap?

    @hagubear: It depends. In some cases the JIT (or even the compiler) is able to avoid allocation (and the overhead it incurs). But unlike in C for example, you are not actually *explicitly* saying where the value should be allocated.

    An object argument is a value type in Java; that is, references are passed by value. You can test this by re-assigning a methods object argument and checking if it indeed alters the original object reference. This would mean the object arguments to a method are stored on the stack.

    Do we have any tool to analyze these memory allocation on heap and stack at time?

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM