{"post":{"slug":"gc-tuning-jvm-2026","title":"JVM GC Tuning: Start With the Collector, Not the Flags","excerpt":"Most JVM garbage collection tuning is flag cargo-culting. Here is how to pick a collector, what to measure, and why heap size is usually the real lever.","category":"code","date":"July 25, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">J</span>VM garbage collection tuning has a folklore problem. Teams copy flag combinations from posts written years ago for different workloads on different hardware, observe no improvement or a regression, and conclude the JVM is inscrutable. Meanwhile the actual lever — which collector is running and how much heap it has — went untouched.\n\nStart there, and most tuning becomes unnecessary.\n\n## What changed in 2026\n\n- **Low-pause collectors matured further.** Concurrent collectors delivering consistently short pauses at large heap sizes became viable for a broader range of applications.\n- **Defaults improved.** Modern JVM defaults became genuinely good for typical workloads, which reduced how much tuning most applications need.\n- **Container awareness became reliable.** Correct detection of container memory limits removed a long-standing source of surprising out-of-memory failures.\n- **Allocation reduction got emphasized.** Guidance shifted toward generating less garbage rather than collecting it faster.\n\n## Choosing a collector\n\n| Priority | Collector characteristics to seek |\n| --- | --- |\n| Throughput on batch work | Parallel collection, longer pauses acceptable |\n| Balanced server workload | Generational concurrent collection, moderate pauses |\n| Low and predictable latency | Concurrent low-pause collector, some throughput cost |\n| Small heap, short-lived process | Simple serial collection; lowest overhead |\n| Very large heap with latency requirements | Concurrent collector designed for large heaps |\n\nThe choice follows from what you are optimizing. A batch job that runs for an hour cares about total throughput and does not care about a pause. A request-serving service cares enormously about the tail of the pause distribution and can afford some throughput loss to shorten it.\n\nGetting this right matters more than any individual flag, and it is frequently the only change needed.\n\n## What to measure\n\nAverage pause time is a nearly useless metric. If most collections pause for a few milliseconds and occasional ones pause for a second, the average looks fine and users experience the second.\n\nMeasure the distribution: median, high percentiles, and the maximum. The high percentiles are what correlate with the latency your users see, and they are what a low-pause collector improves.\n\nAlso measure allocation rate and collection frequency. A high allocation rate means the collector runs constantly regardless of how efficient it is, and reducing garbage generation addresses the cause rather than the symptom. Object pooling, avoiding unnecessary intermediate collections, and reusing buffers in hot paths are frequently more effective than any collector tuning.\n\nEnable garbage collection logging in production. It is low overhead and it is the only way to know what is actually happening rather than inferring from symptoms.\n\n## Heap sizing\n\nToo small and the collector runs constantly, spending a large fraction of CPU time on collection. Too large and, on collectors whose pause scales with heap, individual pauses get long — and you may be reserving memory the application never needs.\n\nThe practical approach is to observe live-set size after a full collection under representative load, then size the heap at a comfortable multiple of that. Enough headroom that collections are not constant, not so much that pauses suffer.\n\nIn containers, ensure the JVM sees the container limit rather than the host's memory. Modern versions handle this correctly by default, and a heap sized against host memory inside a constrained container is a reliable path to termination by the orchestrator.\n\nThe general profiling approach for finding what allocates is in [reading flame graphs](/blog/profiling-flamegraph-guide-2026), and allocation profiles read the same way.\n\n## Common mistakes\n\n- **Copying flag sets from posts.** Tuned for a different workload.\n- **Tuning before choosing the collector.** The dominant decision, frequently skipped.\n- **Optimizing average pause.** The tail is what users feel.\n- **Ignoring allocation rate.** Generating less garbage beats collecting faster.\n- **No GC logging in production.** Diagnosis by guesswork.\n- **Heap sized against host memory in a container.** Terminated by the orchestrator.\n\n## FAQ\n\n**Should I tune at all?**\nModern defaults are good. Start by choosing the right collector for your latency profile and sizing the heap sensibly, then measure before changing anything else.\n\n**How do I reduce allocation?**\nProfile allocations to find the hot paths, then reduce intermediate object creation in those specific places. Broad avoidance of allocation makes code worse for no benefit.\n\n**Does a bigger heap always mean fewer pauses?**\nFewer collections, and on some collectors longer individual pauses. Concurrent collectors designed for large heaps break that relationship, which is why collector choice comes first.\n\n**What about memory leaks?**\nTuning does not fix a leak. Growth that survives full collection is retention — the equivalent procedure for another runtime is in [finding memory leaks in Node](/blog/memory-leak-node-2026).\n\n## Where to go next\n\nFor allocation and CPU analysis, read [reading flame graphs](/blog/profiling-flamegraph-guide-2026). For a different runtime's leak hunting, [finding memory leaks in Node](/blog/memory-leak-node-2026), and for connection resource tuning, [connection timeout tuning](/blog/connection-timeout-tuning-2026).","hue":150,"metaTitle":"JVM GC Tuning Guide: Practical Approach 2026","metaDescription":"How to tune JVM garbage collection — choosing a collector for your latency profile, measuring pause distribution, heap sizing, and reducing allocation rate.","keywords":["gc tuning jvm","garbage collector selection","low latency collector","gc pause distribution","heap sizing java","allocation rate reduction","jvm performance tuning","gc logging analysis","java performance 2026"],"tldr":["**Pick the collector before touching any flag** — collector choice dominates every other tuning decision.","**Measure pause distribution, not average pause** — the tail is what users experience.","**Heap size is usually the highest-impact setting** — too small causes constant collection, too large causes long pauses on some collectors.","**Allocation rate is frequently the real problem** — reducing garbage beats collecting it faster.","**Skip:** copying flag sets from blog posts. They were tuned for a different workload on different hardware."],"readTime":"4 min read","wordCount":804},"related":[{"slug":"allocation-profiling-2026","title":"Allocation Profiling: Finding What Your Code Is Creating","excerpt":"A program with no memory leak can still spend a third of its time in garbage collection. Allocation profiling shows what is being created, which is usually more actionable than what is retained.","category":"code","date":"January 7, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":310},{"slug":"garbage-collection-explained-2026","title":"Garbage collection explained in 2026: how runtimes reclaim memory","excerpt":"GC pauses that once lasted hundreds of milliseconds now target sub-millisecond goals in modern runtimes. Here is how the algorithms work and when they matter.","category":"code","date":"April 13, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":312},{"slug":"connection-timeout-tuning-2026","title":"Connection Timeout Tuning: The Settings Nobody Sets","excerpt":"Default timeouts are usually far too long or absent entirely, which turns a slow dependency into an outage. Here is how to set them deliberately.","category":"code","date":"July 26, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":205}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"counteroffer-strategy-2026","title":"Counteroffers: Negotiating Without Damaging the Relationship","excerpt":"Negotiating an offer is expected and most candidates do not. Here is how to construct a counter that gets a yes.","category":"guides","date":"July 25, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":288},"older":{"slug":"hybrid-search-bm25-2026","title":"Hybrid Search: Why Keywords Still Beat Embeddings Sometimes","excerpt":"Dense retrieval misses exact matches that keyword search finds instantly. Here is how hybrid search combines them, and how fusion actually works.","category":"ai","date":"July 25, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":209}}