Java Garbage Collection Series (Part 3): Advanced Tuning and Choosing the Right Garbage Collector

Divyansh Tripathi
4 min readOct 19, 2024

--

In the previous blogs, we covered the basics of Java garbage collection, including the mark-and-sweep approach and generational GC. Now, let’s dive into the different garbage collectors available in Java and tuning options that allow developers to fine-tune performance based on application needs.

This blog will also cover some essential JVM flags that directly impact garbage collection behavior.

Choosing the Right Garbage Collector

Java provides multiple garbage collectors, each optimized for different workloads. Selecting the right one is critical for balancing throughput, latency, and resource utilization. Here are the three main types:

Serial GC

• Uses a single thread for garbage collection, making it ideal for small applications running on a single-core processor.

Best suited for: Applications that can afford longer GC pauses and need simple GC behavior.

Parallel GC (Throughput Collector)

• Leverages multiple threads to perform garbage collection in parallel, providing higher throughput.

Best suited for: Applications requiring high throughput, where brief pauses are acceptable.

Mostly Concurrent GC (e.g., G1, CMS)

• Aims to reduce GC pauses by performing most of the work concurrently with application threads.

Best suited for: Latency-sensitive applications requiring consistent response times.

G1 Garbage Collector (Garbage First GC)

The G1 GC is designed for large heap sizes and latency-sensitive applications. It divides the heap into regions, allowing garbage collection to focus on areas with the most garbage.

Key Features:

Concurrent marking to identify which regions contain the most garbage.

Evacuation pauses that copy live objects to other regions, reclaiming space efficiently.

Predictable pause times, which make it suitable for real-time or interactive applications.

How G1 Works:

  1. Initial Mark: Marks live objects accessible from GC roots.
  2. Concurrent Mark: Identifies regions with live objects.
  3. Final Mark: Completes marking and prepares for cleanup.
  4. Cleanup: Reclaims garbage-filled regions and moves live objects.

Important JVM Flags for GC Tuning

-version:gc

This command displays the garbage collection algorithms available and their versions in your JVM installation, providing insight into supported GC mechanisms.

Usage Example:

java -version:gc

-XX:-UseAdaptiveSizePolicy

This flag disables the adaptive resizing of heap spaces. When enabled by default, the JVM automatically adjusts heap sizes based on usage patterns.

Disabling this policy allows you to manually control heap sizes for more predictable performance in specific use cases.

NewRatio Flag

The NewRatio flag determines the ratio between the young and old generations in the heap.

Usage Example:

-XX:NewRatio=2

• A ratio of 2 means that the old generation is twice the size of the young generation.

MaxTenuringThreshold Flag

This flag controls how quickly objects are promoted from the young generation to the old generation.

Usage Example:

-XX:MaxTenuringThreshold=5

• Objects surviving 5 minor GCs will be promoted to the old generation. A higher threshold helps delay promotion.

SurvivorRatio Flag

The SurvivorRatio flag sets the ratio between the Eden space and survivor spaces in the young generation.

Usage Example:

-XX:SurvivorRatio=8

• A ratio of 8 means that the Eden space is eight times larger than each survivor space.

ConcGCThreads Parameter

This parameter sets the number of concurrent threads used by the G1 GC during concurrent phases.

Usage Example:

-XX:ConcGCThreads=4

• Increasing the number of threads can reduce GC pause times but may consume more CPU.

InitiatingHeapOccupancyPercent Flag

This flag controls when the G1 GC starts a concurrent cycle based on the percentage of the heap occupied.

Usage Example:

-XX:InitiatingHeapOccupancyPercent=45

• With this setting, G1 GC will start a concurrent cycle when 45% of the heap is occupied.

UseStringDeduplication Flag

This flag enables string deduplication, allowing the JVM to detect and eliminate duplicate strings to save memory.

Usage Example:

-XX:+UseStringDeduplication

• This is especially useful in applications that handle a large number of repeated string values.

Visualizing Garbage Collection with Tools

To optimize garbage collection, you need visibility into how the JVM manages memory. Here are some tools to help monitor GC behavior:

  • VisualVM: Provides real-time memory and GC monitoring.
  • JConsole: Offers a lightweight interface to track heap usage and GC events.
  • GC Logs: Enable GC logging to gain detailed insights into pause times, memory usage, and frequency of collections.

Enabling GC Logging Example:

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log

Conclusion

In this final part of our Java Garbage Collection series, we covered:

• The different types of garbage collectors (Serial, Parallel, and Mostly Concurrent).

Detailed tuning options through important JVM flags.

• A deep dive into the G1 GC, its structure, and performance advantages.

Choosing the right garbage collector and tuning its behavior using JVM flags can have a significant impact on your application’s performance. By monitoring GC events using tools and logs, you can further optimize memory management and ensure smooth application behavior.

This concludes our deep dive into Java garbage collection. Armed with this knowledge, you are now ready to make informed decisions about garbage collection strategies in your Java applications.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Divyansh Tripathi
Divyansh Tripathi

Written by Divyansh Tripathi

Software Developer, Exploring and Learning

Responses (1)

Write a response