안녕하세요.
Netty에는 우리가 파이프라인에 등록한 핸들러 외에 숨겨진 일종의 핸들러가 두 개(TailContext, HeadContext)가 더 있더라구요.
pipeline.addLast(new InboundHandler1()); // #1
pipeline.addLast(new InboundHandler2()); // #2
이렇게 구성된 파이프라인에서 마지막 핸들러인 #2에서 다음 핸들러로 메시지를 던지면 최종적으로 TailContext 라는 곳에서 메시지를 다루게 되는데, 거기서 ReferenceCountUtil.release(msg) 코드가 한 번 더 호출됩니다. 아래 관련된 DefaultChannelPipeline 클래스를 요약해 보았는데 디버그 모드로 한 번 따라가 보면 이해에 도움이 되실 것 같아요.
public class DefaultChannelPipeline implements ChannelPipeline {
...
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail;
...
final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {
...
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
onUnhandledInboundMessage(ctx, msg);
}
}
...
protected void onUnhandledInboundMessage(Object msg) {
try {
...
} finally {
ReferenceCountUtil.release(msg); // <------------------------------------ 여기서 호출 됨
}
}
}