Class LeakPresenceDetector<T>
- java.lang.Object
-
- io.netty.util.ResourceLeakDetector<T>
-
- io.netty.util.LeakPresenceDetector<T>
-
- Type Parameters:
T
- The resource type to detect
- Direct Known Subclasses:
LeakPresenceExtension.WithTransferableScope
public class LeakPresenceDetector<T> extends ResourceLeakDetector<T>
Alternative leak detector implementation for reliable and performant detection in tests.Background
The standard
ResourceLeakDetector
produces no "false positives", but this comes with tradeoffs. You either get many false negatives because only a small sample of buffers is instrumented, or you turn on paranoid detection which carries a somewhat heavy performance cost with each allocation. Additionally, paranoid detection enables detailed recording of buffer access operations with heavy performance impact. Avoiding false negatives is necessary for (unit, fuzz...) testing if bugs should lead to reliable test failures, but the performance impact can be prohibitive for some tests.The presence detector
The leak presence detector takes a different approach. It foregoes detailed tracking of allocation and modification stack traces. In return every resource is counted, so there are no false negatives where a leak would not be detected.
The presence detector also does not wait for an unclosed resource to be garbage collected before it's reported as leaked. This ensures that leaks are detected promptly and can be directly associated with a particular test, but it can lead to false positives. Tests that use the presence detector must shut down completely before checking for resource leaks. There are also complications with static fields, described below.
Resource Scopes
A resource scope manages all resources of a set of threads over time. On allocation, a resource is assigned to a scope through the
currentScope()
method. Whencheck()
is called, or the scope isclosed
, all resources in that scope must have been released.By default, there is only a single "global" scope, and when
check()
is called, all resources in the entire JVM must have been released. To enable parallel test execution, it may be necessary to use separate scopes for separate tests instead, so that one test can check for its own leaks while another test is still in progress. You can overridecurrentScope()
to implement this for your test framework.Static Fields
While the presence detector requires that all resources be closed after a test, some resources kept in static fields cannot be released, or there would be false positives. To avoid this, resources created inside static initializers, specifically when the allocation stack trace contains a
<clinit>
method, are not tracked.Because the presence detector does not normally capture or introspect allocation stack traces, additional cooperation is required. Any static initializer must be wrapped in a
staticInitializer(Supplier)
call, which will temporarily enable stack trace introspection. For example:private static final ByteBuf CRLF_BUF = LeakPresenceDetector.staticInitializer(() -> unreleasableBuffer( directBuffer(2).writeByte(CR).writeByte(LF)).asReadOnly());
Since stack traces are not captured by default, it can be difficult to tell apart a real leak from a missed static initializer. You can temporarily turn on allocation stack trace capture using the
-Dio.netty.util.LeakPresenceDetector.trackCreationStack=true
system property.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
LeakPresenceDetector.ResourceScope
A resource scope keeps track of the resources for a particular set of threads.-
Nested classes/interfaces inherited from class io.netty.util.ResourceLeakDetector
ResourceLeakDetector.LeakListener, ResourceLeakDetector.Level
-
-
Constructor Summary
Constructors Constructor Description LeakPresenceDetector(java.lang.Class<?> resourceType)
Create a new detector for the given resource type.LeakPresenceDetector(java.lang.Class<?> resourceType, int samplingInterval)
Deprecated.LeakPresenceDetector(java.lang.Class<?> resourceType, int samplingInterval, long maxActive)
This constructor should not be used directly, it is called reflectively byResourceLeakDetectorFactory
.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static void
check()
Check the current leak presence detector scope for open resources.protected LeakPresenceDetector.ResourceScope
currentScope()
Get the resource scope for the current thread.boolean
isRecordEnabled()
Check whetherResourceLeakTracker.record()
does anything for this detector.static <R> R
staticInitializer(java.util.function.Supplier<R> supplier)
Wrap a static initializer so that any resources created inside the block will not be tracked.ResourceLeakTracker<T>
track(T obj)
Creates a newResourceLeakTracker
which is expected to be closed viaResourceLeakTracker.close(Object)
when the related resource is deallocated.ResourceLeakTracker<T>
trackForcibly(T obj)
Creates a newResourceLeakTracker
which is expected to be closed viaResourceLeakTracker.close(Object)
when the related resource is deallocated.-
Methods inherited from class io.netty.util.ResourceLeakDetector
addExclusions, getInitialHint, getLevel, isEnabled, needReport, open, reportInstancesLeak, reportTracedLeak, reportUntracedLeak, setEnabled, setLeakListener, setLevel
-
-
-
-
Constructor Detail
-
LeakPresenceDetector
public LeakPresenceDetector(java.lang.Class<?> resourceType)
Create a new detector for the given resource type.- Parameters:
resourceType
- The resource type
-
LeakPresenceDetector
@Deprecated public LeakPresenceDetector(java.lang.Class<?> resourceType, int samplingInterval)
Deprecated.This constructor should not be used directly, it is called reflectively byResourceLeakDetectorFactory
.- Parameters:
resourceType
- The resource typesamplingInterval
- Ignored
-
LeakPresenceDetector
public LeakPresenceDetector(java.lang.Class<?> resourceType, int samplingInterval, long maxActive)
This constructor should not be used directly, it is called reflectively byResourceLeakDetectorFactory
.- Parameters:
resourceType
- The resource typesamplingInterval
- IgnoredmaxActive
- Ignored
-
-
Method Detail
-
staticInitializer
public static <R> R staticInitializer(java.util.function.Supplier<R> supplier)
Wrap a static initializer so that any resources created inside the block will not be tracked. Example:private static final ByteBuf CRLF_BUF = LeakPresenceDetector.staticInitializer(() -> unreleasableBuffer( directBuffer(2).writeByte(CR).writeByte(LF)).asReadOnly());
Note that technically, this method does not actually care what happens inside the block. Instead, it turns on stack trace introspection at the start of the block, and turns it back off at the end. Any allocation in that interval will be checked to see whether it is part of a static initializer, and if it is, it will not be tracked.
- Type Parameters:
R
- The supplier return type- Parameters:
supplier
- A code block to run- Returns:
- The value returned by the
supplier
-
currentScope
protected LeakPresenceDetector.ResourceScope currentScope()
Get the resource scope for the current thread. This is used to assign resources to scopes, and it is used bycheck()
to tell which scope to check for open resources. By default, the global scope is returned.- Returns:
- The resource scope to use
-
track
public final ResourceLeakTracker<T> track(T obj)
Description copied from class:ResourceLeakDetector
Creates a newResourceLeakTracker
which is expected to be closed viaResourceLeakTracker.close(Object)
when the related resource is deallocated.- Overrides:
track
in classResourceLeakDetector<T>
- Returns:
- the
ResourceLeakTracker
ornull
-
trackForcibly
public final ResourceLeakTracker<T> trackForcibly(T obj)
Description copied from class:ResourceLeakDetector
Creates a newResourceLeakTracker
which is expected to be closed viaResourceLeakTracker.close(Object)
when the related resource is deallocated.Unlike
ResourceLeakDetector.track(Object)
, this method always returns a tracker, regardless of the detection settings.- Overrides:
trackForcibly
in classResourceLeakDetector<T>
- Returns:
- the
ResourceLeakTracker
-
isRecordEnabled
public final boolean isRecordEnabled()
Description copied from class:ResourceLeakDetector
Check whetherResourceLeakTracker.record()
does anything for this detector.- Overrides:
isRecordEnabled
in classResourceLeakDetector<T>
- Returns:
true
ifResourceLeakTracker.record()
should be called
-
check
public static void check()
Check the current leak presence detector scope for open resources. If any resources remain unclosed, an exception is thrown.- Throws:
java.lang.IllegalStateException
- If there is a leak, or if the leak detector is not aLeakPresenceDetector
.
-
-