Automatic garbage collection (GC) simplifies and speeds up development, but it’s notorious for causing performance issues in production. In time-critical applications especially, it’s vital to monitor and tune GC to keep systems running as they should.
In this article, we’ll look at the best Java GC monitoring tools to provide information for tuning and troubleshooting.
What is GC and How Does it Affect Performance?
In Java, the GC is a background process that runs in response to certain triggers, including:
- Free space in any memory pool going below a defined threshold;
- Insufficient free space to create a new object (allocation failure);
- Explicit requests by the application program (System.gc()).
GC looks for any objects that no longer have valid references pointing to them and sweeps them from memory. It also compacts memory to prevent fragmentation.
For more information about GC, how it works and how to tune it, this article on Java Garbage Collection is worth a read.
Monitoring Java GC: What Information Do You Need?
To ensure GC is working smoothly, and to make effective tuning decisions, you need to gather information about its activities, such as:
- When did it run?
- How often is it running?
- How long did it take?
- How often and for how long is it stopping application threads for critical activities?
- How much memory was reclaimed, and in what regions?
- Why was it triggered?
GC effectiveness is generally measured by three key performance indicators (KPI):
- Throughput: The percentage of time spent running application threads, as opposed to running GC tasks;
- Latency: The time during which application threads are paused due to critical GC activity. Average and maximum latency are important.
- Footprint: How much CPU time and memory the GC uses.
GC Logging
The GC logs are a valuable source of information.
To enable GC logs, we use command line switches when invoking the JVM.
- For Java 9 and later, the switch is: -Xlog:gc*:file=<gc-log-file-path>
- For Java 8 and earlier, the switches are: -XX:+PrintGCDetails -Xloggc:<gc-log-file-path>
The logs are in text format, and contain details of each GC event. They may look something like this:

Fig: Java GC log
For long-running programs, the logs may be thousands of lines long. Also, the format differs between different GC algorithms and between JVM versions. This is why we need better tools for monitoring Java GC.
Many tools use these logs as the basis for analysis.
What are the Best Java GC Monitoring Tools Included in JDK?
The JDK includes several useful performance monitoring utilities. Let’s look at how to use a few of them to gather information about the garbage collector.
Most of these tools gather data about running Java programs. To do this, they may require the PID (Process ID) of the target program. The quickest way to find this is to run jps from the command prompt:
C:\javadev\>jps14624 Jps14324 BuggyProg2
C:\javadev\>
This lists the PID and name of each running Java application.
The jstat utility allows us to request various kinds of information about the performance of a running JVM process, and what resources it’s using. It’s useful for diagnosing memory and garbage collection issues.
It has a range of run-time switches detailed in the official jstat documentation, and requires a PID as an argument. The documentation also shows the layout of the expected output for each switch.
Switches that are particularly useful when diagnosing GC issues include:
- -gc: This returns detailed statistics relating to GC;
- -gcutil: This returns a summary of GC activity, along with the usage percentage in each memory space
- -gccapacity: This returns the sizes of each memory space, including the minimum, maximum and current usage.
Let’s look at an example using the gcutil option. We want to take 10 samples from a running program at 250 ms intervals, and output the result to a file. We first establish the PID of the required process using jps, and then use jstat with the appropriate switch and arguments.
C:\javadev>jps14324 BuggyProg26600 Jps
C:\javadev>jstat -gcutil 14324 250 10 > jstatout.txt
C:\javadev>
If we then import the file jstatout.txt into a spreadsheet, it looks like this:

Fig: jstat output imported into a spreadsheet
The output columns are as follows:
- S0: Usage % of Survivor Space 0
- S1: Usage % of Survivor Space 1
- E: Usage % of Eden Space
- O: Usage % of Old Generation
- M: Usage % of Metaspace
- CCS: Usage % of Compressed Class Space
- YGC: Young Generation GC Count
- YGCT: Young Generation GC Time
- FGC: Full GC Count
- FGCT: Full GC Time
- CGC: Concurrent GC Count
- CGCTC: Concurrent GC Time
- GCT: Total GC time
This is useful for getting a quick idea of how well GC is working, but it would be a time-consuming task to fully analyze GC performance with this tool.
This utility allows us to send diagnostic commands to a running JVM. It’s useful for a wide range of troubleshooting and monitoring requirements.
It includes lots of different options and arguments, which are detailed in the jcmd official documentation, and requires a PID as an argument.
One of the most useful arguments for monitoring GC is VM.event. This lists detailed information for all JVM events, including GC.
Here’s an example showing how to request details of events and place the output in a text file.
C:\javadev>jps14324 BuggyProg211320 Jps
C:\javadev>jcmd 14324 VM.events > events.txt
C:\javadev>
The output is fairly long, and we have to scroll through it to find the part relevant to GC. This section will be similar to the output in the image below:

Fig: Event Analysis produced by jcmd
This is an all-purpose GUI-based monitoring tool. It doesn’t specifically monitor garbage collection, but shows memory usage over time graphically, which gives a good idea of whether the GC is working efficiently.
To invoke it, type jvisualvm on the command line. This displays a GUI screen similar to the one in the image below.

Fig: Monitoring with jvisualvm
A list of running Java applications appears in the left-hand panel, allowing us to choose a program to monitor. The ‘Monitor’ tab continually displays memory and CPU usage, as well as information about classes and running threads. It has a facility to request garbage collection, allowing us to view the effect on memory and CPU usage.
For more information, see the jvisualvm official documentation.
This is also a GUI-based monitoring tool.
To invoke the utility, type jconsole on the command line. You’ll be asked to choose a process to monitor, after which a GUI screen with tabs for different kinds of information will be displayed.
The VM Summary tab is particularly useful for GC monitoring. Scrolling down it, you’ll find information such as heap usage in each region, the GC algorithm currently in use and the time spent on GC events. This is illustrated in the image below.

Fig: jconsole summary information
The Memory tab is also very useful for assessing whether the GC is working as it should. As with jvisualvm, you can request GC and watch its effect on memory.

Fig: jconsole memory information
jconsole can monitor either local or remote applications. In production, it’s better to run it remotely, since it uses memory and CPU fairly heavily.
For more information, see the jconsole official documentation.
What Are The Best Java GC Monitoring External Tools?
The JVM tools are very useful for getting a quick idea of how well GC is performing, but using them to monitor and analyze performance over time would be a tedious and time-consuming task.
For long-term monitoring and tuning, it’s best to use a reputable external tool, which can fully analyze the logs, or even continually monitor GC performance using APIs. In this section we’ll look at two popular GC monitoring tools.
This is a powerful GUI-based tool. It’s particularly well suited to IBM JVM distributions such as Websphere, but should work with other Java Hotspot installations.
It allows you to view graphs and charts of various GC and memory-related aspects of JVM performance. Its GUI interface lets you choose a metric to view, or even a combination of several metrics. It’s great for experienced users, but beginners may find it difficult to use effectively, since you need to know what you’re looking for.
To use it, you would enable GC logging in your application, and submit the logs to GCMV for analysis
Unfortunately, it doesn’t have API connectivity, so it can’t be used to monitor running applications in real time.
The image below illustrates the GCMV GUI interface.

Fig: IBM GCMV
GCeasy is a simple-to-use powerful GC analyzer. It can work in two ways:
- Provide a comprehensive report within minutes from GC logs;
- Monitor applications in real time using APIs. This option is ideal for including in CD/CI pipelines, and for regularly monitoring applications in production.
Both experienced users and beginners can use it to quickly provide useful information for troubleshooting and tuning Java systems.
GCeasy’s report includes:
- Customized AI suggestions for tuning and troubleshooting the application;
- Allocated vs peak memory usage graphs by region;
- KPI graphs;
- Interactive graphs such as:
- Heap usage before and after GC;
- GC and pause durations;
- Reclaimed bytes by region;
- Stats by GC phase;
- Pause vs concurrent GC time;
- Object and CPU statistics;
- Detection of potential issues such as memory leaks and long pauses;
- GC trigger analysis.
The image below shows sections of some of these graphs and charts.

Fig: Selection of GCeasy graphs and charts
With GCeasy, you can effectively monitor applications regularly with very little time and effort, and pre-empt any issues that may affect production.
Conclusion
Monitoring GC performance is important, since it can have a huge impact on the system if it’s not tuned correctly.
So, what are the best Java GC monitoring tools? For quick, one-off glimpses of GC performance, the tools provided with the JVM are extremely useful. IBM’s GCMV is a good tool for advanced users, but it can be time-consuming to use it for regular system monitoring.
GCeasy is easy to use, provides comprehensive information and can be automated in production or in CD/CI pipelines.
With these tools available, we need never allow GC to impact negatively on system performance.


Share your thoughts!