DefaultResourceLeak Class — netty Architecture
Architecture documentation for the DefaultResourceLeak class in ResourceLeakDetector.java from the netty codebase.
Entity Profile
Dependency Diagram
graph TD 0693d07b_5a78_e1d2_0694_de182ea7e0a6["DefaultResourceLeak"] d32ce738_76fd_52e1_72e6_97f959369f2a["ResourceLeakDetector.java"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|defined in| d32ce738_76fd_52e1_72e6_97f959369f2a d4e09515_5a67_39fd_920d_8c1d27f84d77["DefaultResourceLeak()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| d4e09515_5a67_39fd_920d_8c1d27f84d77 2b39451e_97cf_55c0_71d4_1406fc75aa6c["record()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| 2b39451e_97cf_55c0_71d4_1406fc75aa6c 8f406d36_7022_4ea4_114b_0a77991c8aff["record0()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| 8f406d36_7022_4ea4_114b_0a77991c8aff 836a7c81_609c_0085_1045_b69a2142ec31["dispose()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| 836a7c81_609c_0085_1045_b69a2142ec31 19933ffe_052a_9a22_2cf8_d1cc46f96c9a["close()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| 19933ffe_052a_9a22_2cf8_d1cc46f96c9a b8a1d999_7919_a586_f28b_1b2513c39fe3["reachabilityFence0()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| b8a1d999_7919_a586_f28b_1b2513c39fe3 03052503_d987_b000_6353_5dafed226112["Throwable()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| 03052503_d987_b000_6353_5dafed226112 befe889d_9338_fff8_1c16_76b15e3bd1f6["String()"] 0693d07b_5a78_e1d2_0694_de182ea7e0a6 -->|method| befe889d_9338_fff8_1c16_76b15e3bd1f6
Relationship Graph
Source Code
common/src/main/java/io/netty/util/ResourceLeakDetector.java lines 399–639
@SuppressWarnings("deprecation")
private static final class DefaultResourceLeak<T>
extends WeakReference<Object> implements ResourceLeakTracker<T>, ResourceLeak {
@SuppressWarnings({"unchecked", "rawtypes"}) // generics and updaters do not mix.
private static final AtomicReferenceFieldUpdater<DefaultResourceLeak<?>, TraceRecord> headUpdater =
(AtomicReferenceFieldUpdater)
AtomicReferenceFieldUpdater.newUpdater(DefaultResourceLeak.class, TraceRecord.class, "head");
@SuppressWarnings({"unchecked", "rawtypes"}) // generics and updaters do not mix.
private static final AtomicIntegerFieldUpdater<DefaultResourceLeak<?>> droppedRecordsUpdater =
(AtomicIntegerFieldUpdater)
AtomicIntegerFieldUpdater.newUpdater(DefaultResourceLeak.class, "droppedRecords");
@SuppressWarnings("unused")
private volatile TraceRecord head;
@SuppressWarnings("unused")
private volatile int droppedRecords;
private final Set<DefaultResourceLeak<?>> allLeaks;
private final int trackedHash;
DefaultResourceLeak(
Object referent,
ReferenceQueue<Object> refQueue,
Set<DefaultResourceLeak<?>> allLeaks,
Object initialHint) {
super(referent, refQueue);
assert referent != null;
this.allLeaks = allLeaks;
// Store the hash of the tracked object to later assert it in the close(...) method.
// It's important that we not store a reference to the referent as this would disallow it from
// be collected via the WeakReference.
trackedHash = System.identityHashCode(referent);
allLeaks.add(this);
// Create a new Record so we always have the creation stacktrace included.
headUpdater.set(this, initialHint == null ?
new TraceRecord(TraceRecord.BOTTOM) : new TraceRecord(TraceRecord.BOTTOM, initialHint));
}
@Override
public void record() {
record0(null);
}
@Override
public void record(Object hint) {
record0(hint);
}
/**
* This method works by exponentially backing off as more records are present in the stack. Each record has a
* 1 / 2^n chance of dropping the top most record and replacing it with itself. This has a number of convenient
* properties:
*
* <ol>
* <li> The current record is always recorded. This is due to the compare and swap dropping the top most
* record, rather than the to-be-pushed record.
* <li> The very last access will always be recorded. This comes as a property of 1.
* <li> It is possible to retain more records than the target, based upon the probability distribution.
* <li> It is easy to keep a precise record of the number of elements in the stack, since each element has to
* know how tall the stack is.
* </ol>
*
* In this particular implementation, there are also some advantages. A thread local random is used to decide
* if something should be recorded. This means that if there is a deterministic access pattern, it is now
* possible to see what other accesses occur, rather than always dropping them. Second, after
* {@link #TARGET_RECORDS} accesses, backoff occurs. This matches typical access patterns,
* where there are either a high number of accesses (i.e. a cached buffer), or low (an ephemeral buffer), but
* not many in between.
* <p>
* The use of atomics avoids serializing a high number of accesses, when most of the records will be thrown
* away. High contention only happens when there are very few existing records, which is only likely when the
* object isn't shared! If this is a problem, the loop can be aborted and the record dropped, because another
* thread won the race.
*/
private void record0(Object hint) {
// Check TARGET_RECORDS > 0 here to avoid similar check before remove from and add to lastRecords
Source
Frequently Asked Questions
What is the DefaultResourceLeak class?
DefaultResourceLeak is a class in the netty codebase, defined in common/src/main/java/io/netty/util/ResourceLeakDetector.java.
Where is DefaultResourceLeak defined?
DefaultResourceLeak is defined in common/src/main/java/io/netty/util/ResourceLeakDetector.java at line 399.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free