- Heap Memory and Stack Memory in Java
- Introduction
- What is Stack Memory in Java?
- Example of Stack Memory in Java
- What is StackOverflowError in Java?
- What is Heap Memory in Java?
- New or Young Generation
- Old or Tenured Generation
- Permanent Generation
- Example of Heap Memory in Java
- Why OutOfMemoryError is thrown in Java?
- Differences Between Stack and Heap Memory
- Advantages of using Stack Memory in Java
- Disadvantages of using Stack Memory in Java
- Advantages of using Heap Memory in Java
- Disadvantages of using Heap Memory in Java
- Conclusion
Heap Memory and Stack Memory in Java
Stack Memory is the Static Memory Allocation Scheme where all the function calls, primitive data values specific to a method and references to the objects in the heap memory are stored. Access to stack memory is in Last-In-First-Out (LIFO) order.
Heap Memory is used for Dynamic Memory Allocation of Java objects and JRE classes that are created during the execution of a Java program. Heap memory is allocated to objects at runtime and these objects have global access which implies they can be accessed from anywhere in the application.
Introduction
Java Applications are compiled and executed in the RAM of the computers. Each application is allocated a certain amount of memory. This allocated memory in RAM is called Application Memory. The amount of memory allocated to a Java process depends on multiple factors like Java Runtime Environment (JRE) , operating system, processor, etc.
The memory in the JVM is divided into into five parts:
- Stack
- Heap
- Class/Method Area
- Program Counter Register
- Native Method Stack
In this article, we will be diving deep into stack and heap memory in Java.
What is Stack Memory in Java?
Stack Memory is the Static Memory Allocation Scheme where all the function calls, primitive data values specific to a method and references to the objects in the heap memory are stored. Stack memory is always accessed in a Last-In-First-Out (LIFO) manner.
Changes in Stack Memory when a method is called:
- In the stack memory, a new memory block is created for every method that is called. All the primitive data values specific to that method and references to objects referred from the method are stored in this memory block.
- When the method completes its execution, the memory block is cleared from the stack memory and the stack memory is available for use.
- The values in the stack exist for as long as the function that created them is in execution. The size of the stack memory is fixed and cannot grow or shrink once created.
Example of Stack Memory in Java
Below is a simple Java program with three methods main , addOne , and addTwo . We will see the step-by-step explanation of the stack usage when this program executes.
- When the program is executed, the main method is executed first by the JVM . When the main method is called, a block is allocated for it in the call stack.
- The main method contains one primitive value x. This primitive value is stored in the memory block allocated for the main method.
- When the addOne method is called from the main method, a new block for addOne method is allocated in the stack memory.
- The variables specific to the method are created and stored in the allocated memory block. Upon the completion of the execution of the method, the value is returned to the calling method(here it is the main method), and the block is removed from the call stack.
- Similarly, when the addTwo method is called, a new block is allocated for it, and the variables are created and stored. When the method finishes execution, the value is returned to the calling method, and the block is cleared.
- Finally, the main method completes its execution, and the memory block corresponding to main method is cleared from the stack.
What is StackOverflowError in Java?
As mentioned earlier, stack memory is limited in size and cannot be enlarged or shrunk once created. Therefore, if we use all of the stack memory, there will be no space left for upcoming method calls, and we will get the StackOverflowError .
Explanation:
- A new block on the stack is allocated for each call to the factorial method.
- When the above program is executed, the factorial method will be called indefinitely because the base case is commented.
- As the stack size is fixed, and the factorial method is called indefinitely and doesn’t return any value, so the stack memory runs out, resulting in StackOverflowError .
What is Heap Memory in Java?
Heap memory is used to store the objects that are created during the execution of a Java program. The references to the objects that are created in the heap are stored in the stack memory. Heap follows dynamic memory allocation scheme (memory is allocated during execution or at runtime) and provides random and global access to objects created, unlike stack, which follows Last-In-First-Out (LIFO) memory access order.
The size of heap memory is large when compared to stack. The unused objects in the heap memory are cleared automatically by the Garbage Collector in Java.
The heap memory can be divided into three parts:
- New or Young Generation
- Old or Tenured Generation
- Permanent Generation
New or Young Generation
Young generation is the memory space where all the newly created objects are allocated. New generation in turn has 3 parts, Eden, Survivor1 and Survivor2. All the newly created objects are allocated in Eden space. When the Eden is full, a minor garbage collection happens, and the live objects are moved to Survivor1 and then to Survivor2.
The Survivor1 and Survivor2 contains objects that survived the minor garbage collection. Objects that survive Eden, Survivor1 and Survivor2 are moved to Old generation. In Old generation the garbage is collected less frequently, so Survivor1 and Survivor2 spaces are used to make sure that only long survived objects are moved to tenured generation.
Old or Tenured Generation
Age is set for the objects allocated in young generation. When that age is met, those live objects are moved to the old generation. Generally, long-surviving objects are stored in the old generation. A major garbage collection runs on the old generation to collect dead objects.
Permanent Generation
Permanent generation is used by JVM to store metadata about the classes and methods. JVM also stores Java standard libraries in permanent generation. This space is cleaned as a part of full garbage collection.
Example of Heap Memory in Java
Explanation:
In the above example, the variable x is allocated in the stack, whereas the object list is allocated memory in the heap. Only the reference to the list object is stored in the stack memory alongside x .
Why OutOfMemoryError is thrown in Java?
OutOfMemoryError is thrown when there is no more space left in the heap to create and store a new object. This happens when the Garbage Collector could not freeup any space to store new objects.
Explanation:
Consider the above program where we are repeatedly generating arrays of bigger sizes and storing values in them. Once the space ran out in the heap, it threw OutOfMemoryError .
Differences Between Stack and Heap Memory
Property | Stack Memory | Heap Memory |
---|---|---|
Size | The size of stack memory is smaller | The size of heap memory is larger |
Order | Stack memory is accessed in Last-In-First-Out (LIFO) manner | Heap memory is dynamically allocated and does not follow any order |
Speed | Access to stack memory is faster because of Last-In-First-Out (LIFO) ordering | Access to heap memory is slower because it does not follow any order and is allocated dynamically |
Resizing | Resizing of variables is not allowed in stack | Resizing of variables is allowed in a heap |
Allocation | Memory is allocated and deallocated automatically when a method starts and completes its execution respectively | Memory is allocated when objects are created and deallocated by the garbage collector when they are no longer in use |
Storage | Primitive values specific to a method and object references from the method are stored in the stack | The newly created objects and the JRE classes are stored in heap |
Exception | StackOverflowError is thrown when there is no more space left in the stack for new method calls | OutOfMemoryError is thrown when there is no space left in a heap to allocate new objects |
Thread Safety | Each thread is allocated with a new stack, and it is thread-safe | Heap memory is shared across all threads, and it is not thread-safe |
Scope | Stack memory is used only by one thread of execution. | Heap memory is used by all the parts of the application. |
Lifetime | Stack memory is short lived. | Heap memory lives from the start till the end of application execution. |
Advantages of using Stack Memory in Java
- Stack memory is thread-safe because each thread has its stack area.
- Memory allocation and deallocation are faster.
- Memory is automatically allocated and deallocated for a method.
- Access to stack memory is faster.
Disadvantages of using Stack Memory in Java
- Stack memory is fixed and cannot grow or shrink once created.
- Stack memory works in Last-In-First-Out (LIFO) manner. So, random access is not possible.
- Stack memory is neither scalable nor flexible.
Advantages of using Heap Memory in Java
- Heap memory is not fixed, and it can grow and shrink.
- Heap memory doesn’t flow any ordering and allows random access.
- Heap memory is scalable and flexible.
- Objects created in the heap memory can be accessed from anywhere in the application.
Disadvantages of using Heap Memory in Java
- Heap memory is shared across threads and is not thread-safe.
- Access to heap memory is slower.
- Memory allocation and deallocation is complex when compared to stack.
Conclusion
- Stack and Heap memory are allocated to an application by the Java Virtual Machine (JVM) .
- Stack Memory in Java is used for the execution of a thread and static memory allocation.
- Stack memory contains method specific primitive values and references to objects in the heap that are getting referred from the method.
- Stack memory is accessed in a Last-In-First-Out (LIFO) order.
- The size of the stack memory is small and fixed.
- Stack can be used when the scope of the variable is not used outside the method scope, the access to the memory should be faster, and the variables should be thread-safe.
- All the objects created are stored in a heap.
- The size of the heap is large when compared to the stack.
- Heap memory follows dynamic allocation and has three parts, New Generation , Young Generation , and Permanent Generation .
- Heap memory can be used when the scope is global and objects need to be accessed across threads.