[netty5: LifecycleTracer & ResourceSupport]-源码分析

发布于:2025-07-09 ⋅ 阅读:(13) ⋅ 点赞:(0)

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,因此它和它的子类(UnsafeBufferNioBufferMemSegBuffer)能够利用 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);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到