As a Java developer, memory management and garbage collection is one topic you need to understand well. If you are having issues understanding these concepts, no need to worry.
This post will explain the entire concepts in details while giving examples. At the end of this post, you should understand the following concepts well:
- Memory Management in Java
- Garbage Collection in Java
- Types of Memory in Java
- Garbage Collection Process
- Types of Garbage Collectors in Java
Introduction To Concepts
There are some basic concepts you need to know that will help you understand this topic better.
. Memory In Java:
This refers to the allocated space where objects, variables and data are stored in the process of executing a java application. In other words, every variable, object or other data types the developer inputs in the process of creating a java program is stored in memory.
. Memory management:
Memory Management is the process of allocation and deallocation of memory space for objects during the exaction of an application. This process takes place in the Java Virtual Machine JVM.
. Garbage Collection:
This, on the other hand is the process of cleaning up the memory space. How it works is that the garbage collector identifies and removes objects that are no longer referenced in the heap memory.
In some programming languages like C and C++, it’s the work of the programmer to manually handle the memory management process. The programmer is expected to manually allocate and deallocate memory space while creating the application.
Thankfully, Java handles the process automatically via garbage collection. The garbage collection process is better than manual because it helps to prevent the issue of dangling reference. You will understand how the garbage collection process works later in this post.
. Dangling Reference:
This error occurs when a reference or pointer still points to a memory location in the heap memory that has been reallocated or removed.
Types Of Memory In Java
As mentioned earlier, memory in Java is the space where data is stored during the process of executing a program. There are three types of memory spaces in Java. They include:
- Stack Memory
- Heap Memory
- MetaSpace Memory
Let’s explain each of the memory types in details now.
. Stack Memory:
The stack memory is the section of the memory where method invocation takes place. Method invocation happens when a new method is created, a scope is created in the stack memory to store the data in the method. That includes, local variables and parameters.
The stack memory is always smaller than the heap memory. Also, during the garbage collection process, the stack memory gets cleaned up first. The process happens automatically when a method is done executing.
The types of data that is stored in the Stack memory includes:
- Primitive Values/ Temporary Variables.
- Memory block for methods (Scope).
- Reference of an object. Note that the object itself is stored in the heap memory while the reference is stored in the stack memory.
- Thread. Each thread has its own stack memory while all threads share a common heap memory.
Finally, the stack memory throws the ‘stackoverflow’ error when it is full.
. Heap Memory
The heap memory is the section of the memory where objects are stored. It is larger than the stack memory. The heap memory is divided into two main sessions, the young generation and the old generation.
The young generation is further divided into Eden Space and Survivor Space. The Survivor space is further divided into S0 and S1 spaces. You will understand the types of the heap memory and their functions later in this post.
. MetaSpace Memory
The metaspace was previously known as the Permanent Generation before the Java 7 version, and was a part of the heap memory. The Permanent Generation was not expandable and throws a heap error once the memory is full.
Now, it has evolved to metaspace memory, which is a stand-alone memory space from the heap memory. The metaspace stores class variables, constants, annotations, and class metadata. In other words, information about the class from which objects are created including constants (static and final) are stored in the metaspace memory.
The JVM loads the class if it needs it and removes if from the metaspace when it has no need for it. One good thing about the metaspace is that it is expandible.
Diagram To Explain Data Storage In Java Memory.
public class Main { public static void main(String[] a) { int seat = 4; String str1 = "30"; String str2 = new String ("30") Car newCar = new Car(); } public void method2(){ String str3 = "30"; Car newCar2 = new Car(); } }
How Memory Management Works In Java
The memory management process frees up space in memory for incoming data. Here is how the process work; when a method is done executing, the JVM cleans up the stack memory automatically. The values and variables in the method are forgotten.
The JVM does not clean up the heap memory automatically when a method is done executing because the object on the heap may be needed by another method which is still in the stack memory.
An object becomes eligible for garbage collection when it no longer has a reference in the stack memory.
Java Virtual Machine JVM initiates the garbage collection process automatically. The developer can suggest to the JVM to start the garbage collection process by executing ‘System.gc( )’ code, but it doesn’t guarantee that it will start the process.
How Garbage Collection Works In Java
The space that a method occupies in the stack memory is known as a scope. The closing bracket in a method marks the end of a scope and the cleanup process starts. All variables and references in the method are removed.
The JVM deletes the scope starting from the latest scope. It applies the last in, first out cleanup process. After the variables and object references in the stack memory is removed, the garbage collection process starts in the heap memory. The garbage collector deletes the unreferenced objects in the heap memory.
The first garbage collection process is called the mark and sweep algorithm process. The garbage collector checks for and marks dead objects (objects without reference) and separates them from live objects (objects with reference). Objects with no references are moved to the Eden space.
The surviving objects is swept to either the S0 or S1 which is known as the survivor space. The survivor space has a threshold as new objects are created and the garbage collection process continues.
Once the survivor space gets to its threshold, it is promoted to old generation space in the heap memory.
The garbage collection process runs more frequently in the new generation than in the old generation. This is because objects moved to the old generation are used frequently and may have several references pointing to them indirectly.
Note that the garbage collection process that takes place in the young generation is known as the minor garbage collection while that of the old generation is known as major garbage collection.
Knowledge of when to promote an object from young to old generation is vital in the garbage collection process.
The garbage collector uses different collection strategies or algorithms for each generation. For instance, it can use the mark – sweep strategy for the
Types Of Garbage Collection Process In Java
There are three main collection process the garbage collector applies to clean up memory space. They include the following:
. Normal Mark Sweep:
The process here involves two processes. The mark and the sweep process. First, go through the heap memory to identify and mark live objects from dead objects. After that, the garbage collector initiates the sweep process.
That is sweeping or removing dead objects to the next memory space. It starts from the Eden space and the remaining objects are moved to the Survivor space.
After the removal of the dead objects remaining objects remains or maintains initial spaces. This method is not ideal especially if the incoming objects are bigger and can’t fit in the between the space.
Note: that the Garbage Collection Cycle is the amount of time it takes the garbage collector to complete a full garbage collection round.
. Mark Sweep With Compact:
After the garbage collector complete the collection cycle, it compacts the remaining objects to free up space for new objects. This way, there is enough space for incoming objects.
. Mark Sweep Copy:
Here, the garbage collector marks objects from the ‘from space’ region and moves them to the ‘to space’ region. After that, it compacts the remaining objects to free space for new objects.
Types of Garbage Collection Algorithms
There are five garbage collection algorithms in java. Here is a breakdown of each collection algorithm, features and where it applies:
. Serial Garbage Collector:
This garbage collector algorithm is good for a single core machine. It uses the mark- sweep for young generation and mark sweep compact for the old generation. The serial garbage collector runs on a single thread. This means that other threads in the program will pause (Stop-The-World) during the garbage collection process.
Pros:
- Suitable for programs with small data sets where the pause time does not matter.
Cons:
- Slow because it runs on a single thread.
- More expensive.
. Parallel Garbage Collector:
This collector works as the default garbage collector in java. The Parallel collector uses the mark sweep copy for young generation and mark sweep compact for old generation.
It uses multiple threads to perform garbage collection. The program gets pause time during the garbage collection process but for a shorter amount of time. It runs well on a multi core machine.
Pros:
- Faster than the serial collector
Cons:
- Slower than other garbage collector algorithms below.
. Concurrent Mark Sweep Garbage Collector:
This is an upgrade from the previous parallel collector. It uses the mark sweep copy for young generation and concurrent mark sweep for the old generation and uses multiple threads to perform garbage collection.
This collection method does not require the program to stop. The garbage collection process runs concurrently with execution of the program. Mostly, it uses the concurrent collection method, but will revert back to stop-the-world if there is need for it.
. Garbage First (G1) Garbage Collector:
This was first introduced in Java 7 and uses multiple threads to perform garbage collection. It divides the heap memory into small regions. It applies the parallel, concurrent, and incrementally compacting collection methods.
The G1 collector has the shortest pause time because of the division of the heap memory to small regions (memory segments). It keeps track of live and dead objects in each memory segment. The segment with the greatest number of objects is collected first. Stop-the-world (pause time) happens but for a shorter time period. This collector algorithm is best for machines with large memory space and high performance.
. Z Garbage Collector:
This was first introduced in Java 11. Also, uses multiple threads to perform garbage collection. Here, the garbage collection method is completed while the program is running concurrently with less than 10 milliseconds of pause time.
The garbage collection process starts with marking live objects with reference coloring and not with maps as with other collectors. The reference states are stored in bytes of the reference.
The Z garbage collector works well on 64 bits machines as the references does not have enough bits to execute on a 32 bit system. Also, it applies fragmented memory as a result of the garbage collection process. These entire process runs concurrently with the program hence the 10 milliseconds pause time.
Conclusion
So far, this post has all you need to know about memory management in java. Finally, if you are wondering which garbage collection algorithm is best for your program. The answer is, it depends. It depends on the program in question, and the system. For example, the serial collector method is best for a small program with minor data sets.