To understand the Java garbage collection mechanism, it is important to understand the JVM memory pattern first. Today we will understand the various parts of the JVM's memory, how to monitor it, and the garbage collection tuning.
Java (JVM) memory model
As you can see from the above picture, the JVM memory is divided into separate sections. Broadly speaking, JVM heap memory is divided into two parts -young Generation and old Generation.
Young Generation
The young generation is where all new objects are generated. Garbage collection is triggered when the memory space of the young generation is exhausted. This garbage collection is called the Minor GC. The young generation is divided into 3 parts of the --enden District and two survivor districts .
Highlights of the young generation space:
- Most new objects are located in the Eden area.
- When the Eden area is filled with objects, the minor GC is executed. and transfer all surviving objects to one of the survivor areas.
- The Minor GC also checks for surviving objects and transfers them to another survivor area. In this way, there will always be an empty survivor area for a period of time.
- After several GC cycles, the surviving objects are transferred to the old generation memory space. This is usually done by setting an age threshold before the younger generation is eligible to ascend to the old age.
Old Generation
Older generations of memory contain long-lived objects and objects that survived multiple Minor GC . Garbage collection is usually done in the old years when memory is full. Garbage collection in the old age is called Major GC. Major GC will take more time.
Stop the World event
All garbage collection is "Stop the World" event, because all application threads will stop until the operation is complete (so called "Stop the World").
Because the objects in the young generation are temporary (short-lived) objects, executing the minor GC is very fast, so the app will not be affected by ("Stop the World").
Because the major GC checks for all surviving objects, it takes longer. Major GC should be minimized. Because the major GC makes your app unresponsive during garbage collection, you'll see a time-out error if you have an application that needs a quick response that happens multiple times major GC.
Garbage collection time depends on the garbage collection policy. This is why it is necessary to monitor garbage collection and to tune garbage collection. This avoids time-out errors for applications that require fast response.
Permanent Generation
The permanent generation or "Perm Gen" contains the application metadata required by the JVM, which describes the classes and methods used in the application. Note that the permanent generation is not part of the Java heap memory.
Permanently stores the classes used by the JVM runtime. The permanent generation also contains classes and methods for the Java SE library. A permanent object is garbage collected at full GC.
Method Area
A method area is part of a permanent generation space and is used to store type information (run constant and static variables) and method code and constructor code.
Memory Pool
If the JVM implements support, the JVM memory management creates an object pool for the immutable object to create the memory pool. A string pool is a good example of a memory pool type. The memory pool can belong to a heap or a permanent generation, depending on the implementation of the JVM memory management.
run a constant-rate pool
The run-time constant pool is the runtime representative of each class of const pool. It contains the run-time and static methods of the class. Running a constant pool is part of the method area.
Java Stack Memory
Java stack memory is used to run threads. They contain temporary data from the method and specific data referenced by other objects in the heap. You can read the difference between stack memory and heap memory.
Java heap Memory Switch
Java provides a large number of memory switches (parameters) that we can use to set the memory size and their proportions. Here are some common switches:
VM Switch |
VM Switch Description |
-xms |
Sets the initialization size of the heap when the JVM starts. |
-xmx |
Sets the maximum heap value. |
-xmn |
Set the size of the young generation's space, leaving the space for the old age. |
-xx:permgen |
Sets the initialization size for the permanent generation of memory. |
-xx:maxpermgen |
Sets the maximum value for the permanent generation. |
-xx:survivorratio |
Provides the spatial proportions of the Eden and survivor areas. For example, if the size of the young generation is 10m and the VM switch is-xx:survivorratio=2, then 5m memory will be reserved for the Eden Zone and each survivor area to allocate 2.5m memory. The default scale is 8. |
-xx:newratio |
Provides the proportion of old and young generations. The default value is 2. |
Most of the time, the above options are enough to use. But if you still want to know about other options, check out the official JVM Options page.
Java garbage Collection
Java garbage collection finds useless objects, removes them from memory, and frees up memory for objects created later. One of the biggest advantages of the Java programming language is automatic garbage collection , unlike other programming languages where you need to manually allocate and free memory, such as the C language.
The garbage collector is a background run program. It manages all objects in memory and finds objects that are not referenced. All of these unreferenced objects are deleted, their space is reclaimed and assigned to other objects.
A basic garbage collection process involves three steps:
- Tags: this is the first step. In this step, the garbage collector will find out what objects are being used and which objects are not in use.
- Normal Purge: The garbage collector clears the objects that are not in use, and reclaims their space for allocation to other objects.
- compression cleanup: to improve performance, compression cleanup moves all surviving objects together after removing useless objects. This can improve the efficiency of assigning new objects.
There are two problems with simple tagging and purging methods:
- Efficiency is low. Because most new objects will become "useless objects."
- Objects that pass through multiple garbage collection cycles are likely to survive in later cycles.
The problem with the simple cleanup method above is that Java garbage collection is recycled , and there are two regions in the heap memory for young generation and older generations . I've explained how minor GC and major GC scan objects, and how to move objects from one generational space to another.
Java garbage collection types
There are five types of garbage collection that you can use in your app. Only the JVM switch is required to enable the garbage collection policy in our application. Let's take a look at:
- Serial GC (-XX:+USESERIALGC):Serial GC uses simple tagging, purging, and compression methods for garbage collection of young and old generations, that is, minor GC and major GC. The Serial GC is useful in client mode, such as in simple standalone applications and lower CPU configurations. This pattern works well for applications that occupy less memory.
- Parallel GC (-XX:+USEPARALLELGC): in addition to generating n threads for a young generation of garbage collection, Parallel GC and serial GC are almost the same. Here n is the number of cores of the system CPU. We can use the-xx:parallelgcthreads=n this JVM option to control the number of threads. The parallel garbage collector is also called the throughput collector. Because it uses multiple CPUs to speed up garbage collection performance. The Parallel GC uses a single thread for old generation garbage collection.
- Parallel old GC (-XX:+USEPARALLELOLDGC): same as Parallel GC. In contrast, the Parallel old GC uses multi-threaded collection when it comes to young generation garbage collection and older generation garbage collections.
- Concurrency Token Cleanup (CMS) collector (-XX:+USECONCMARKSWEEPGC):The CMS collector is also known as a transient pause concurrency collector. It is a garbage collection for old generations. The CMS collector collects garbage from multiple threads concurrently, minimizing the pauses caused by garbage collection. The CMS collector uses the same algorithm as the parallel collector for garbage collection for younger generations. This garbage collector is suitable for applications that cannot tolerate long pauses requiring rapid response. You can use the-xx:parallelcmsthreads=n JVM option to limit the number of threads for the CMS collector.
- G1 garbage collector (-XX:+USEG1GC) G1 (Garbage first): The garbage collector is a feature that can be used after Java 7, and its long-term goal is to replace the CMS collector. The G1 collector is a parallel, concurrent, and incremental compressed garbage collector that briefly pauses. The G1 collector does not operate in the same way as other collectors, and does not differentiate between young and old generation spaces. It divides the heap space into areas of equal size. When garbage collection is done, it takes precedence over areas where there are fewer surviving objects, so it is called "garbage first". You can find more details in the Oracle Garbage-first collector documentation.
Java garbage Collection monitoring
We can use command line and graphical tools to monitor the monitoring application garbage collection. For example, I use a demo from the Java SE download page to experiment.
If you want to use the same app, you can download JDK 7 and JavaFX demos and Samples to the Java SE download page. The sample app I'm using is Java2demo.jar, which is located in the jdk1.7.0_55/demo/jfc/java2d directory. This is only an optional step and you can run a GC monitoring command to monitor any Java application.
The commands I use to open the demo app are:
1 |
[email protected]:~ /Downloads/jdk1 .7.0_55 /demo/jfc/Java2D $ java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar |
Jsat
You can use the jstat command-line tool to monitor JVM memory and garbage collection. The standard JDK already comes with jstat, so there's no need to do anything extra to get it.
To run Jstat you need to know the app's process ID, you can use Ps-eaf | grep java command gets the process ID.
123 |
[email protected]:~$ ps -eaf | grep Java2Demo.jar 501 9582 11579 0 9:48PM ttys000 0:21.66 /usr/bin/java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar 501 14073 14045 0 9:48PM ttys002 0:00.00 grep Java2Demo.jar |
As I know from above, my Java app process ID is 9582. You can now run the jstat command, as shown below:
123456789 |
[email protected]:~$ jstat -gc 9582 1000
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
|
The last parameter of the Jstat command is the time interval for each output. Memory and garbage collection data are printed every second.
Let's come together to understand the meaning of each column:
- s0c and s1c: This column shows the current size (in kilobytes) of the SURVIVOR0 and Survivor1 regions.
- s0u and s1u: This column shows the current usage of the Survivor0 and Survivor1 zones (in kilobytes). Note: At any time, there will always be a survivor area that is empty.
- EC and EU: These columns show the current space size and usage (in kilobytes) of the Eden area. Note: The size of the EU has been increasing. And as long as the size is close to EC, the minor GC is triggered and the EU will be reduced.
- OC and OU: These columns show the current space size and current usage (in kilobytes) of the old generation.
- pc and PU: These columns show the current space size and current usage (in kilobytes) of the Perm Gen (permanent generation).
- YGC and YGCT: YGC This column shows the number of GC events that occurred in the younger generation. YGCT This column shows the cumulative time to perform GC operations in the younger generation. Note: When the value of the EU is reduced due to the minor GC, both YGC and YGCT on the same row increase.
- FGC and FGCT: The FGC column shows the number of times a full GC event has occurred. FGCT shows the cumulative time for full GC operations. NOTE: The full GC takes much longer than the GC usage time for younger generations.
- GCT: This column shows the total cumulative time of the GC operation. Note: The total cumulative time is the sum of the time used by the YGCT and fgct two columns (GCT=YGCT+FGCT).
Jstat , we can also run Jstat on a remote server without a GUI. Note: We are using the-XMN10M option to specify the sum of s0c, S1C, and EC as 10m.
Java VISUALVM and Visual GC plugins
If you want to see the memory and GC in the GUI, you can use the JVISUALVM tool. Java VISUALVM is also part of the JDK, so you don't need to download it separately.
Run the JVISUALVM command at the terminal to start the Java VISUALVM program. Once the program is started, you need to install the Visual GC plugin from the Tools->plugins option, as shown in the image below.
After the visual GC plugin is installed, open the app from the left sidebar and move the view to the Visual GC section. You will get details about JVM memory and garbage collection as shown in.
Java garbage Collection tuning
Java garbage Collection tuning should be the last option to increase application throughput. Java garbage collection tuning should be considered when you find that your app has degraded its performance due to long garbage collection and time-outs.
If you see Java.lang.OutOfMemoryError:PermGen space errors in the log, you can try using the-xx:permgen and-xx:maxpermgen JVM options to monitor and increase the perm gen memory space. You can also try using-xx:+cmsclassunloadingenabled and view execution performance using the CMS garbage collector.
If you see a lot of full GC operations, then you should try to increase the memory space of the old age.
Full garbage collection tuning takes a lot of effort and time, and there's no hard tuning rule that doesn't change. You need to try different options and compare these options to find the best solution for your application.
This is all the Java memory model and garbage collection content. Hopefully it will help you understand the JVM's memory and garbage collection processes.
Java Memory garbage Collection tuning