[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 编码查看转换 | 代码下载 | 常见问题及讨论 | Python游戏编程讨论 | 《深入解析ASP核心技术》 | Python游戏编程教程 | AI图片生成
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[备忘]netty,ChunkedFile,channelInactive()时没有释放file引用,导致文件删除不掉。

上一篇:[备忘]netty报错:BlockingOperationException
下一篇:[备忘]session共享,redisson配置问题。

添加日期:2025/12/4 15:47:25 快速返回   返回列表 阅读26次
现状大概是这样:
ChunkedFile cf= new ChunkedFile(file);
channel.writeAndFlush(cf);
做一个ChunkedFile,然后直接写channel。

问题:
上传文件时,恰好发现连接断开了。
file的引用没有释放,导致后续再次上传后,无法删除文件。
ChunkedFile里实际就是包装了一个RandomAccessFile对象。
----------------------------------------------------
在ChannelPipeline里是这样:
p.addLast(new ChunkedWriteHandler());//发送大文件

看了ChunkedWriteHandler的代码,各种处理很仔细,成功失败都有close动作。
有点困惑。
----------------------------------------------------
在业务Handler里,channelInactive()方法发现channel inactive后,直接重新连接了。
所以问题在于,连接断开时,没有释放file的引用。

然后突然想到,channelInactive()方法会触发哪个Hander来处理呢?

问了机器人,答案是:链式处理,从尾巴到Head。
----------------------------------------------------

当 Channel 变为非活动状态时,channelInactive() 会从 pipeline 的尾端向头端 传播:
ChannelInboundHandler1 → ChannelInboundHandler2 → ... → TailContext
实际上事件是从 TailContext 开始,向 HeadContext 方向传播(即从尾到头)。


public class ChannelInactiveExample {
    public static void main(String[] args) {
        ChannelPipeline pipeline = ...;
        
        // 添加 handler(按顺序)
        pipeline.addLast("handler1", new MyHandler("handler1"));
        pipeline.addLast("handler2", new MyHandler("handler2"));
        pipeline.addLast("handler3", new MyHandler("handler3"));
        
        // 触发 channelInactive 时,调用顺序是:
        // handler3 → handler2 → handler1
    }
    
    static class MyHandler extends ChannelInboundHandlerAdapter {
        private String name;
        
        public MyHandler(String name) {
            this.name = name;
        }
        
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println(name + ": channelInactive");
            super.channelInactive(ctx); // 重要:继续传播
        }
    }
}



必须调用 super.channelInactive(ctx)!!!!
如果不调用父类方法,事件传播会中断。
所以,根本原因是业务Handler的channelInactive()方法没有调用super.channelInactive(ctx)!!!!
导致ChunkedWriteHandler的channelInactive()方法没有执行,没有释放file引用。

ChunkedWriteHandler.java
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        doFlush(ctx);
        ctx.fireChannelInactive();
    }
    
    private void doFlush(final ChannelHandlerContext ctx) {
        final Channel channel = ctx.channel();
        if (!channel.isActive()) {
            discard(null);
            return;
        }
    在discard()里会closeInput(in);



在父类:
ChannelInboundHandlerAdapter.java中有:
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelInactive();
    }
所以,业务Handler里应该调用super.channelInactive()方法!!!!!除非真的不需要!!!
    
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved