在调用静态open方法创建java.nio.channels.SocketChannel对象后,必须调用close方法关闭SocketChannel对象以释放创建的文件句柄(fd)资源,否则如果不断地创建SocketChannel对象会使得打开文件的句柄数达到系统设定的上限,从而出现 “Too many open files”的问题。
现象:1)通过netstat -n | wc -l 查看连接数并不多; 2)系统或jvm报Too many open files; 3)通过命令ls -l /proc/<pid>/fd | grep socket |wc -l 查看有大量与socket关联的文件句柄。
原因分析:
下面是java.nio.channels.SocketChannel的open方法,该方法调用SelectorProvider.provider().openSocketChannel()创建SocketChannel对象。
public static SocketChannel open() throws IOException {
return SelectorProvider.provider().openSocketChannel();
}
我们先看SelectorProvider.provider()返回的对象。如果没有提供自定义的SelectorProvider实现,SelectorProvider.provider()会返回sun.nio.ch.DefaultSelectorProvider.create()创建的SelectorProvider对象,在linux下是sun.nio.ch.EPollSelectorProvider。
sun.nio.ch.EPollSelectorProvider的openSocketChannel()方法继承了sun.nio.ch.SelectorProviderImpl的实现,而sun.nio.ch.SelectorProviderImpl的openSocketChannel()直接返回创建的sun.nio.ch.SocketChannelImpl对象,其构造函数如下:
SocketChannelImpl(SelectorProvider sp) throws IOException {
super(sp);
this.fd = Net.socket(true);
this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED;
}
sun.nio.ch.Net.socket(boolean stream)的实现如下:
static FileDescriptor socket(boolean stream) {
return IOUtil.newFD(socket0(stream, false));
}
IOUtil.newFD的实现如下
static FileDescriptor newFD(int i) {
FileDescriptor fd = new FileDescriptor();
setfdVal(fd, i);
return fd;
}
可见,在创建SocketChannelImpl对象时创建了一个文件句柄,尽管这个文件句柄尚未和socket绑定,但已经开始占用系统的fd资源。所以在使用SocketChannel后一定要调用close()方法,尤其是在创建socket时出现异常时,一定要调用SocketChannel.close()方法将fd资源关闭/释放,否则就会出现上面的现象连接数不高,但文件句柄数很高。
分享到:
相关推荐
例如,书中提到了使用 Java NIO 可以提高应用程序的响应性、可扩展性和可靠性等。 ### Java NIO API 与旧版 I/O API 的关系 值得注意的是,Java NIO API 是对旧版 I/O API 的补充而非替代。这意味着开发者需要了解...
Java.nio,全称为Java Non-blocking Input/Output,是Java平台从1.4版本开始引入的一套全新的I/O API,旨在替代传统的Java.io流API。它提供了更高效、更灵活的I/O操作方式,特别是在处理大量并发连接时,性能显著...
Java NIO支持多种类型的通道,包括文件通道(FileChannel)、套接字通道(SocketChannel)和服务器套接字通道(ServerSocketChannel)等。通道可以同时进行读写操作,并且可以实现异步读写。 2. **缓冲区(Buffers...
在探讨Java.nio与Java.io之间的比较时,我们首先需要理解这两个包在Java编程语言中的核心作用和它们各自的优势。Java.io和Java.nio是Java中处理输入/输出操作的两个主要框架,它们各自拥有独特的特性和应用场景。 #...
而Java.NIO则采用了非阻塞模式,允许在读写操作未完成时线程继续执行,显著提升了并发处理能力。 #### 关键特性解析 1. **缓冲区(Buffer)** - Java.NIO的核心之一是缓冲区的概念。缓冲区实际上是一个容器,用于...
JDK1.7 之 java.nio.file.Files 读取文件仅需一行代码实现 java.nio.file.Files 类是 JDK1.7 中引入的新的文件操作类,该类包含了许多有用的方法来操作文件。其中,Files.readAllBytes(Path) 方法可以将整个文件...
【java.nio.file库详解】 Java 早期版本的文件I/O操作功能相对有限,存在几个显著问题:不支持现代文件系统特性、API设计复杂且冗长、处理大文件和并发性能不足。为了解决这些问题,Java引入了`java.nio.file`库,...
找了好久,终于找到了,java刷新同步获取网络资源
Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java应用程序提供了非阻塞I/O操作的能力,与传统的IO模型(基于流的I/O和基于缓冲区的I/O)相比,NIO具有更高的效率和灵活性。在Java NIO中,数据是以通道...
### Java NIO 详细教程知识点解析 #### 一、Java NIO 概述 Java NIO(New IO)是Java平台提供的一种新的IO操作模式,它首次出现在Java 1.4版本中,并在后续版本中不断完善。Java NIO 的设计目的是为了克服传统Java ...
2. `java.nio.channels`:这个包包含一系列Channel接口和它们的实现,如FileChannel、SocketChannel等。Channel代表了一个开放的I/O资源,数据可以通过Channel进行传输。Selector是这个包中的另一个重要组件,它允许...
下面的示例用法( require 'me.moocar.java.io)( require '[clojure.java.io :as jio])( import '(java.nio.file Paths))( def p ( Paths/get " /tmp " ( into-array [ " foo " ])))( with-open [writer ( jio/...
java.NIO与Files工具类(解决方案).md
java.NIO与Files工具类(处理方案示例).md
Java NIO,全称为New Input/Output,是Java在1.4版本引入的一个新的I/O API,用于替代标准的Java IO API。这个新的API提供了一种不同于传统阻塞I/O模型的非阻塞I/O处理方式,使得在处理高并发、大数据传输场景时性能...
《Apress.Pro.Java.7.NIO.2.2011》这本书专注于讲解Java 7中的非阻塞I/O(Non-blocking I/O, NIO)和NIO 2的高级特性,是Java开发者深入理解这一关键领域的重要参考资料。NIO在Java平台中扮演着至关重要的角色,特别...
o Clojure对java.nio的支持。 将clojure.java.io的输入流,输出流和复制功能扩展到java.nio类。 定义新的强制功能缓冲区,字节缓冲区,字符缓冲区,双缓冲区,浮点缓冲区,整数缓冲区,长缓冲区,短缓冲区,通道,可...