Backend Development 14 min read

Debugging and Resolving Netty Long‑Connection Memory Leak Issues

This article details a real‑world Netty long‑connection memory‑leak case, explains how to reproduce the problem, uses Netty's advanced leak detection to pinpoint the faulty ByteBuf usage, and presents three practical remediation strategies to permanently fix the leak.

JD Tech
JD Tech
JD Tech
Debugging and Resolving Netty Long‑Connection Memory Leak Issues

The article introduces a memory‑leak incident that occurred in a Netty‑based long‑connection service used for payment scenarios, describing the background, the urgency of the problem, and the typical advantages of long connections over short‑polling.

It explains that the service exhibited a slow but steady increase in off‑heap memory consumption, eventually triggering frequent restarts, and that log entries containing the keyword "LEAK" revealed that ByteBuf.release() was not called before garbage collection.

To investigate, the author enabled Netty's advanced leak detection ( -Dio.netty.leakDetectionLevel=advanced ), reproduced the issue locally with a reduced JVM heap, and used JProfiler to monitor memory growth. The detailed leak log pinpointed the source to LongRotationServerHandler.getClientMassageInfo(LongRotationServerHandler.java:169) , as shown in the captured log snippet:

2020-09-24 20:11:59.079 [nioEventLoopGroup-2-8] ERROR io.netty.util.ResourceLeakDetector [171] - LEAK: ByteBuf.release() was not called before it's garbage-collected.
#5: io.netty.buffer.AdvancedLeakAwareCompositeByteBuf.readBytes(AdvancedLeakAwareCompositeByteBuf.java:476)
... 
com.jd.jr.keeplive.front.service.nettyServer.handler.LongRotationServerHandler.getClientMassageInfo(LongRotationServerHandler.java:169)

The article then outlines three common ways to release a ByteBuf : manual release, upgrading the handler to SimpleChannelHandler (which automatically releases), and delegating to ReferenceCountUtil.release(msg) . Considering API stability and safety, the third approach was chosen, with an illustrative code fragment:

if (msg instanceof ByteBuf) {
    ReferenceCountUtil.release(msg);
}

After applying the fix, the service’s memory usage stabilized, no further leak logs appeared, and the long‑connection service operated normally in production.

Finally, the article summarizes Netty’s leak‑detection levels (DISABLED, SIMPLE, ADVANCED, PARANOID) and recommends best practices such as running tests at PARANOID level, monitoring in SIMPLE before full deployment, and using ADVANCED during gray releases to locate leaks.

debuggingJavaBackend DevelopmentNettymemory leakReference Counting
JD Tech
Written by

JD Tech

Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.