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();
@Override
public 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();
}
}
}
@Override
public 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);
}
@Override
public boolean isAccessible() {
return acquires >= 0;
}
@Override
public 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;
}
@Override
public AdaptableBuffer<T> touch(Object hint) {
super.touch(hint);
return this;
}
@Override
public boolean equals(Object o) {
return o instanceof Buffer && InternalBufferUtils.equals(this, (Buffer) o);
}
@Override
public int hashCode() {
return InternalBufferUtils.hashCode(this);
}
}