[netty5: LifecycleTracer ResourceSupport]-源码分析
LifecycleTracer
@UnstableApi
public abstract class LifecycleTracer {// 默认关闭static final boolean lifecycleTracingEnabled = SystemPropertyUtil.getBoolean("io.netty5.buffer.lifecycleTracingEnabled", false);// 重点!public static LifecycleTracer get() {// 生命周期追踪未启用 且 泄漏检测关闭if (!lifecycleTracingEnabled && LeakDetection.leakDetectionEnabled == 0) {return NoOpTracer.INSTANCE;}return new StackTracer();}public abstract void allocate();public abstract void acquire(int acquires);public abstract void drop(int acquires);public abstract void close(int acquires);public abstract void touch(Object hint);public abstract <I extends Resource<I>, T extends ResourceSupport<I, T>> Owned<T> send(Owned<T> instance);public abstract void splitTo(LifecycleTracer splitTracer);public abstract <E extends Throwable> E attachTrace(E throwable);public abstract Collection<TracePoint> collectTraces();// NoOpTracer// StackTracer, Trace, Traceback// TraceType // AttachmentType
}
TraceType
用于记录资源生命周期中发生的关键事件。
枚举值 | 含义 |
---|---|
ALLOCATE | 分配资源(如内存)时发生的事件。 |
ACQUIRE | 从池中获取(重用)资源的事件。 |
CLOSE | 显式关闭资源的事件。 |
DROP | 底层释放资源(drop 操作)。 |
SEND | 资源被发送的事件(如跨线程)。 |
RECEIVE | 资源被接收的事件。 |
TOUCH | 调用 touch(Object hint) 时记录的事件。用于定位资源流向。 |
SPLIT | 缓冲区被拆分为子缓冲区的事件。 |
private enum TraceType {ALLOCATE,ACQUIRE,CLOSE,DROP,SEND,RECEIVE,TOUCH,SPLIT,
}
AttachmentType
用于连接不同资源之间的因果或传递关系。
枚举值 | 含义 |
---|---|
SEND_FROM | 表示当前追踪器是被“发送自”哪个追踪器。 |
RECEIVED_AT | 表示当前追踪器“接收到”哪个资源。 |
SPLIT_FROM | 当前追踪器是从哪个对象拆分来的。 |
SPLIT_TO | 当前追踪器拆分出去形成了哪个对象。 |
HINT | 来源于 touch(hint) 中的 hint 参数。 |
private enum AttachmentType {SEND_FROM,RECEIVED_AT,SPLIT_FROM,SPLIT_TO,HINT,
}
ResourceSupport
提供对资源生命周期追踪的支持,主要通过 LifecycleTracer 进行资源的生命周期管理。它是一个基础类,可以为所有继承它的资源类型提供生命周期追踪功能。
@UnstableApi
public abstract class ResourceSupport<I extends Resource<I>, T extends ResourceSupport<I, T>> implements Resource<I> {private int acquires; // Closed if negative.private Drop<T> drop;private final LifecycleTracer tracer;protected ResourceSupport(Drop<T> drop) {this.drop = drop;tracer = LifecycleTracer.get();tracer.allocate();}@SuppressWarnings("unchecked")static <T> T acquire(ResourceSupport<?, ?> obj) {return (T) obj.acquire();}static LifecycleTracer getTracer(ResourceSupport<?, ?> obj) {return obj.tracer;}protected final T acquire() {if (acquires < 0) {throw attachTrace(createResourceClosedException());}if (acquires == Integer.MAX_VALUE) {throw new IllegalStateException("Reached maximum allowed acquires (" + Integer.MAX_VALUE + ").");}acquires++;tracer.acquire(acquires);return impl();}protected abstract RuntimeException createResourceClosedException();@Overridepublic final void close() {if (acquires == -1) {throw attachTrace(new IllegalStateException("Double-free: Resource already closed and dropped."));}int acq = acquires;acquires--;if (acq != 0) {// Only record a CLOSE if we're not going to record a DROP.tracer.close(acq);} else {// The 'acquires' was 0, now decremented to -1, which means we need to drop.tracer.drop(0);try {drop.drop(impl());Reference.reachabilityFence(this); // Avoid racing with any Cleaner.} finally {makeInaccessible();}}}@Overridepublic final Send<I> send() {if (acquires < 0) {throw attachTrace(createResourceClosedException());}if (!isOwned()) {throw notSendableException();}try {var owned = tracer.send(prepareSend());return new SendFromOwned<>(owned, drop, getClass());} finally {acquires = -2; // Close without dropping. This also ignore future double-free attempts.makeInaccessible();}}protected <E extends Throwable> E attachTrace(E throwable) {return tracer.attachTrace(throwable);}protected IllegalStateException notSendableException() {return new IllegalStateException("Cannot send() a reference counted object with " + countBorrows() + " borrows: " + this + '.');}static boolean isOwned(ResourceSupport<?, ?> obj) {return obj.isOwned();}protected boolean isOwned() {return acquires == 0;}static int countBorrows(ResourceSupport<?, ?> obj) {return obj.countBorrows();}protected int countBorrows() {return Math.max(acquires, 0);}@Overridepublic boolean isAccessible() {return acquires >= 0;}@Overridepublic I touch(Object hint) {if (isAccessible()) {tracer.touch(hint);}return self();}protected abstract Owned<T> prepareSend();protected void makeInaccessible() {}protected Drop<T> unsafeGetDrop() {return drop;}protected void unsafeSetDrop(Drop<T> replacement) {drop = Objects.requireNonNull(replacement, "Replacement drop cannot be null.");}@SuppressWarnings("unchecked")private I self() {return (I) this;}@SuppressWarnings("unchecked")private T impl() {return (T) this;}
}
AdaptableBuffer
AdaptableBuffer
继承自 ResourceSupport,因此它和它的子类(UnsafeBuffer
, NioBuffer
,MemSegBuffer
)能够利用 ResourceSupport 提供的资源生命周期追踪功能。
public abstract class AdaptableBuffer<T extends ResourceSupport<Buffer, T>> extends ResourceSupport<Buffer, T> implements Buffer {protected final AllocatorControl control;protected AdaptableBuffer(Drop<T> drop, AllocatorControl control) {super(drop);this.control = control;}@Overridepublic AdaptableBuffer<T> touch(Object hint) {super.touch(hint);return this;}@Overridepublic boolean equals(Object o) {return o instanceof Buffer && InternalBufferUtils.equals(this, (Buffer) o);}@Overridepublic int hashCode() {return InternalBufferUtils.hashCode(this);}
}