Java Memory Management: Understanding the JVM, Heap, Method Area, Stack
If you’re seeking a simplified explanation of the concepts of young generation, old generation, and permanent generation in Java, you’ve come to the correct source.
Generations? What are they?
Basically, we’re discussing Java’s garbage collection.
Garbage collection and Java
In languages such as C, programmers must meticulously manage memory by allocating and deallocating it as needed.
In contrast, Java features automatic garbage collection, which relieves developers from the burden of manually handling memory allocation and deallocation. The underlying notion is that most programmers need not concern themselves with these low-level memory tasks, if at all.
Simply put, in Java, objects are stored in the heap or heap memory. The garbage collection algorithm employed by Java scans the heap, identifying and marking objects that are still actively used by the Java Virtual Machine (JVM). Subsequently, any objects that were not marked are considered unused, and their memory is reclaimed by the garbage collector.
While the intricacies of the garbage collection algorithm are beyond the scope of this discussion, it is crucial to understand the concept of marking and the division of the heap into smaller segments known as generations.
In the provided diagram, we encounter the terms “young generation,” “old generation,” and “permanent generation.” However, don’t be intimidated by it; the fundamental concepts are actually quite easy to grasp.
Young Generation
At a high level, the young generation is the initial destination for newly created objects in Java. When objects are allocated in the Java code, they are specifically placed in a subsection known as the eden space within the young generation.
The eden space becomes populated with objects. Once it becomes full, a minor garbage collection event takes place.
This is where the previously mentioned marking algorithm becomes significant. During this phase, the objects that are referenced (marked) are moved to another subsection within the young generation called S0 in the survivor space (which is divided into S0 and S1). Meanwhile, the objects that are unreferenced (unmarked) are cleared out by Java’s automatic garbage collection mechanism.
This pattern continues until the eden space becomes full once more, triggering a new cycle. The events described in the previous paragraph are repeated, but with a slight difference. In this cycle, since S0 has already been populated, all the marked objects that survive from both the eden space and S0 are moved to the second part of the survivor space known as S1. In the diagram below, these sections are labeled as the “from survivor space” and the “to survivor space” respectively.
One very important thing to note that any objects that make it to the survivor space gets tagged with an age counter. The algorithm will check this to see if it meets a threshold to go to the next stage: the old generation. More on that in a later section.
Cool, let’s take a moment to gather our thoughts, as the next cycle of garbage collection may seem a bit unusual, but it’s not overly complex. When the eden space becomes full once again and initiates another minor garbage collection, the marked (referenced) objects are not placed directly into S1 as before. Instead, there is a switch between the “from” and “to” survivor spaces.
The provided diagram should help illustrate the switching of the “from” and “to” survivor spaces. The key takeaway here is that objects don’t necessarily move from S0 to S1 within the survivor space. Instead, they alternate their destination with each minor garbage collection event.
To summarize, it suffices to understand that new objects begin in the eden space and gradually transition to survivor spaces as they survive multiple garbage collection cycles. This knowledge should provide a satisfactory level of understanding without delving too deeply into the intricacies.
Old Generation
The old generation can be perceived as the repository for long-lived objects. Essentially, if objects surpass a certain age threshold through multiple garbage collection events in the young generation, they are eligible to be transferred to the old generation.
When objects are garbage collected from the old generation, it triggers a major garbage collection event.
Now, let’s examine the process of promoting objects from the survivor space of the young generation to the old generation.
In the given example, any objects that have survived a certain number of cycles (in this case, 8 cycles, but note that it’s just an example and can vary) in the survivor space are moved by the algorithm to the old generation.
The old generation is represented by a single section known as the tenured generation. This is why, in conversations or readings, the terms “old generation” and “tenured generation” are often used interchangeably.
Permanent Generation
There’s an important point to note: the permanent generation is not populated by objects from the old generation when they reach a certain threshold and are moved (promoted) to the permanent generation. This is not the way it works!
Instead, the permanent generation is initially populated by the JVM with metadata that represents the classes and methods of the application at runtime. This metadata is immediately stored in the permanent generation.
Occasionally, the JVM may adhere to specific rules for cleaning out the permanent generation, and when this occurs, it is referred to as a full garbage collection.
Stop The World?
A “stop the world” event sounds pretty dramatic, but think of it in terms of the Java application being the world.
During both minor garbage collection (young generation) and major garbage collection (old generation), a “stop the world” event occurs. This means that all application threads come to a complete halt and must wait until the garbage collection event finishes before they can resume their execution. The pausing of the application threads ensures the integrity and correctness of the garbage collection process.
Thank you)