java nio里的channel是实现自InterruptibleChannel接口的,这个接口的注释里有说明,当正在操作这个channel的线程被其他线程中断,则会close这个channel,当前(被中断的)线程抛出一个ClosedByInterruptException异常。

我们今天在排查一个问题时,用户线程执行了下面的调用过程(从上往下):

org.apache.catalina.connector.CoyoteOutputStream.flush ---》

org.apache.tomcat.util.net.NioChannel.write ---》

sun.nio.ch.SocketChannelImpl.write ---》

java.nio.channels.spi.AbstractInterruptibleChannel.end // 这里抛出异常

来看一下这个sun.nio.ch.SocketChannelImpl.write 方法内部,它的详细代码可以看这里) 这里简化一些:

public int write(ByteBuffer buf) throws IOException {

...

synchronized (writeLock) {

...

try {

begin();

...

} finally {

...

end(n > 0 || (n == IOStatus.UNAVAILABLE));

...

}

}

}

主要看一下它里面的begin和end,先看end方法,异常抛出的地方:

protected final void end(boolean completed)

throws AsynchronousCloseException

{

blockedOn(null);

Thread interrupted = this.interrupted;

if (interrupted != null && interrupted == Thread.currentThread()) {

interrupted = null;

throw new ClosedByInterruptException();

}

if (!completed && !open)

throw new AsynchronousCloseException();

}

可以看到ClosedByInterruptException异常抛出的前提是当前线程被标记为已中断的;而这个判断是在begin方法里做的:

protected final void begin() {

if (interruptor == null) {

interruptor = new Interruptible() {

public void interrupt(Thread target) {

synchronized (closeLock) {

if (!open)

return;

open = false;

interrupted = target;

try {

AbstractInterruptibleChannel.this.implCloseChannel();

} catch (IOException x) { }

}

}};

}

blockedOn(interruptor);

Thread me = Thread.currentThread();

if (me.isInterrupted()) // 检测当前线程是否已中断

interruptor.interrupt(me);

}

在begin方法里,检查当前线程如果是中断状态,用引用记录起来(为了后边比较使用),并关闭了channel。

现在用scala模拟一下这个异常:

$ cat server

import java.nio._

import java.net._

import java.nio.channels._

val serverSock = ServerSocketChannel.open()

serverSock.socket().bind(new InetSocketAddress(54321))

val ch:SocketChannel = serverSock.accept()

println("ok,received")

Thread.currentThread().interrupt() //中断当前线程

try{

ch.socket().getOutputStream().write(200)

}catch{

case e:Throwable => println(e)

}

上面的这段脚本,用nio模拟了一个server等待客户端的链接,当链接过来的时候,中断当前线程,然后继续channel进行处理的时候会捕获到ClosedByInterruptException异常。

启动上面的脚本

$ scala server

在另一个终端下模拟一次client请求:

$ telnet localhost 54321

这时会看到server端的输出信息:

$ scala server

ok,received

java.nio.channels.ClosedByInterruptException

java nio 捕获异常_java nio channel抛出ClosedByInterruptException的情况相关推荐

  1. java 是否继续_Java异常被抛出或被捕获之后,代码是否继续执行的问题

    在写程序的时候,我们经常被教导,要对异常的信息进行处理,哪里该抛出异常.但是,更多的时候,我们只是模仿异常的抛出,却不知道为什么要这样抛异常(被catch了?被向上抛了?后面的代码是否执行了?). 接 ...

  2. java 在方法中抛出异常_Java异常的抛出

    在Java中,当定义的方法可能产生异常时,程序员必须抛出可能的异常. 抛出异常的两种方式,一是在方法内部用throw语句,二是在方法定义时用throws关键字 1.throw语句 在Java中,thr ...

  3. java搭云梯_java nio为什么是通道(一):通往nio的云梯

    java nio的通道是一个全新的I/O实现,没有扩展或者继承其它的类或者包. 通过只能在字节缓冲区上操作,因此Channel是面向字节的接口,为什么要这样设计呢?主要是因为通道直接会和操作系统的I/ ...

  4. java nio多路复用_Java NIO系列教程(六) 多路复用器Selector

    多路复用器Selector是Java NIO编程的基础,熟练地掌握Selector对于掌握NIO编程至关重要.多路复用器提供选择已经就绪的任务的能力.简单来讲,Selector会不断地轮询注册在其上的 ...

  5. Java nio 异常_java.nio.BufferOverflowException 异常问题

    系统运行一段时间,tomcat就会一直抛出下面的异常,造成系统不能访问,是什么原因? 2018-11-30 10:20:43,014 org.nutz.mvc.impl.processor.FailP ...

  6. java 向上抛异常_java throws 向上抛出的概念问题

    展开全部 ------------------附注------------------------ 向上抛出的意思 针对  子类 父类, 这里面涉及到几个方面,最重323131333532363134 ...

  7. java nio 事件_Java NIO原理及实例

    Java NIO是在jdk1.4开始使用的,它既可以说成"新I/O",也可以说成非阻塞式I/O.下面是java NIO的工作原理: 1. 由一个专门的线程来处理所有的 IO 事件, ...

  8. java bytebuffer 读写_java nio bytebuffer文件读写问题

    为什么下面的代码从文件中读不出3和2来?importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOExc ...

  9. java nio 详_java nio详解

    一. 分布式rpc框架有很多,比如dubbo,netty,还有很多其他的产品.但他们大部分都是基于nio的, nio是非阻塞的io,那么它的内部机制是怎么实现的呢. 1.由一个专门的线程处理所有IO事 ...

  10. java 最后的异常_java – 最后不要抛出堆栈溢出异常

    Error不是例外.所以捕捉任何异常都不会捕获StackOverflowError. 所以让我们先来看一下"明显的错误" – (这段代码不太适合这个答案后面的说明): catch( ...

最新文章

  1. BaseTDI.sys 瑞星卡巴冲突,导致机器蓝屏
  2. Python ATM
  3. 争论不休的TF 2.0与PyTorch,到底现在战局如何了? | 技术头条
  4. Java9新功能之HTTP2和REPL
  5. c字符串函数实现(1)---strncpy
  6. emwin edit控制的输入长度小数点怎么处理_变频器学习,变频器主电路与控制回路学习...
  7. Vertx JDBC 批处理
  8. 大数据之-Hadoop之HDFS的API操作_文件下载案例---大数据之hadoop工作笔记0058
  9. win32开发(绘制bitmap)
  10. UVA11192 Group Reverse【水题】
  11. 免费画图软件推荐 - draw.io
  12. Altium Designer 18生成Gerber教程
  13. 档案系列包括图书馆管理与服务器,基于Web的图书馆档案管理系统设计与实现.pdf...
  14. Ubuntu12.04软件安装指南
  15. 八核处理器真的比四核性能强悍吗?
  16. VB.NET 打开Excel文件,读取Excel内容,添加到DataGridView中并显示
  17. 学术会议日常英语交流_有效的日常会议的3个问题
  18. 封神台旧靶场-kali系列
  19. 机械行业如何实现多级经销订货在线化?试试数商云B2B电商系统
  20. python unescape函数_Python escape.url_unescape方法代碼示例

热门文章

  1. 计算机网络课程思政教学目标,计算机学院举行课程思政示范教学活动
  2. libtorrent源码分析(四)LSD实现
  3. matlab 如何查数据类型,MATLAB数据类型
  4. windows 如何录制电脑自身内部的声音,无需 (Stereo mix )立体声混合选项
  5. 两个命令行应用程序的交互——使用Java的Process类完成复杂控制台程序的自动化操作(以围棋GTP协议为例)
  6. 话费充值哪里便宜?这样充帮我省了不少钱,推荐给您
  7. python网页登录验证码_15.Python实现识别登录验证码(入门)
  8. 【数据结构】从零实现顺序表+链表相关操作
  9. Arduino ESP8266 AP Web 服务器示例程序
  10. HTTP协议-报文解析