Java applications need a certain amount of RAM on a computer to run. Each time an object or variable is declared, it needs more RAM. Simply designating enough memory to hold every value declared and run each method would lead to a bloated application.
To keep application memory requirements lean, it is partitioned in ways that require less memory and allows the application to run more quickly.
The Java Virtual Machine (JVM) divides memory between Java Heap Space and Java Stack Memory in a way that only uses memory that’s needed.
It is created by the Java Virtual Machine when it starts. The memory is used as long as the application is running. Java runtime uses it to allocate memory to objects and Java Runtime Environment (JRE) classes.
When an object is created, it is always created in Heap and has global access. That means all objects can be referenced from anywhere in the application.
It is managed by two concepts: Garbage collection and young-generation, old-generation.
Garbage collection works to free memory by clearing any by objects without any references in the methods. These are objects that are no longer being used. Clearing them ensures they don’t take up space in the Heap.
Young-generation, old-generation helps prioritize objects for garbage collection by dividing Java Heap Space into two generations.
The nursery is the younger generation where the new objects are stored. When the nursery is full, garbage collection cleans it out. Note only the memory space for the nursery is full. There is still memory in the old generation.
The old generation is home to objects have been around long enough. When the old generation runs out of room, garbage collection removes the objects not being used in the old space. Again, only part of the Heap is full when old garbage collection happens. There is still room in the nursery.
This is the temporary memory where variable values are stored when their methods are invoked. After the method is finished, the memory containing those values is cleared to make room for new methods.
When a new method is invoked, a new block of memory will be created in the Stack. This new block will store the temporary values invoked by the method and references to objects stored in the Heap that are being used by the method.
Any values in this block are only accessible by the current method and will not exist once it ends.
When the method ends, that block will be erased. The next method invoked will use that empty block.
This “last in, first out” method makes it easy to find the values needed and allows fast access to those values.
Let’s look at a very simple example of a Java application to see how memory is allocated.
package com.journaldev.test;package com.journaldev.test; public class Memory { public static void main(String[] args) { // Line 1 int i=1; // Line 2 Object obj = new Object(); // Line 3 Memory mem = new Memory(); // Line 4 mem.foo(obj); // Line 5 } // Line 9 private void foo(Object param) { // Line 6 String str = param.toString(); //// Line 7 System.out.println(str); } // Line 8 }
In the above example from JournalDev.com, the use of Stack and Heap is explained as follows:
To learn more, check out the following resources:
Stack and heap are two ways Java allocates memory. Understanding when and how they work is critical for developing better Java programs.
It’s also helpful to understand how allocation works when dealing with memory leaks. Additional tools for Java for you to explore include Prefix to write better Java code for free and the full lifecycle APM, Retrace.
If you would like to be a guest contributor to the Stackify blog please reach out to stackify@stackify.com