Java的IO演进

jspet 10年前

在JDK1.4推出Java NIO之前,基于Java的所有Socket通信都采用了同步阻塞模式(BIO),这种——请求——应答的通信模型简化了上层的应用开发,但是在性能和可靠性方面却存在着巨大的瓶颈。因此,在很长一段时间里,大型的应用服务器都采用C或者C++语言开发,因为它们可以直接使用操作系统提供的异步I/O(AIO)能力。当并发访问量增大,响应时间延迟增大之后,采用Java BIO并发的服务端软件只有通过硬件的不断扩容来满足高并发和低延时,它极大地增加了企业的成本,并且随着集群规模的不断膨胀,系统的可维护性也面巨大的挑战,只能通过采购性能更高的硬件服务器来解决问题,这会导致恶性循环。

正是由于Java传统BIO的拙劣表现,才使得Java支持非阻塞I/O的呼的呼声日渐高涨,最终,JDK1.4版本提供了新的NIO类库(new input/output),Java终于也可以支持非阻塞I/O了。从JDK1.0到JDK1.3,Java的I/O类库都非常原始,很多UNIX网络编程中的概念或者接口在I/O类库中都没有体现,例如:Pipe,Channel,Buffer和Selector等。2002年发布JDK1.4时,NIO以JSR-51的身份正式随JDK发布。NIO主要的类和接口如下:

  • 进行异步I/O操作的缓冲区ByteBuffer等;

  • 进行异步I/O操作的管道Pipe;

  • 进行各种I/O操作(异步或者同步)的Channel,包括ServerSocketChannel和SocketChannel;

  • 多种字符集的编码能力和解码能力;

  • 实现非阻塞I/O操作的多路复用器Selector;

  • 基于流行的Perl实现的正则表达式类库;

  • 文件通道FileChannel; 

新的NIO类库的提供,极大地促进了基于Java的异步非阻塞编程的发展和应用,但是,它依然有不完善的地方,特别是对文件系统的处理能力仍显不足,主要问题如下:

  • 没有统一的文件属性(例如读写权限)

  • API能力比较弱,例如目录的级联创建和递归遍历,往往需要自己实现。

  • 底层存储系统的一些高级API无法使用。

  • 所有的文件操作都是同步阻塞调用,不支持异步文件读写操作。

2011年7月28日,JDK1.7正式发布。它的一个比较大的亮点就是将原来的NIO类库进行了升级,被称为NIO2.0。NIO2.0由JSR-203演进而来,它主要提供了如下三个方面的改进

  • 提供能够批量获取文件属性的API,这些API具有平台无关性,不与特性的文件系统相耦合,另外它还提供了标准文件系统的SPI,供各个服务提供商扩展实现

  • 提供AIO功能,支持基于文件的异步I/O操作和针对网络套接字的异步操作

  • 完成JSR-51定义的通道功能,包括对配置和多播数据报的支持等。