JDK7的NIO.2在Linux上是否使用了Epoll等技术?

7
我正在研究不同语言中的网络IO API结构,并对Java中的异步IO API如何实现有疑问。旧版(1.4之前)的流式IO API提供同步阻塞读/写功能。JDK 1.4 NIO API使用 epoll/select 来测试IO的准备就绪状态(通过SelectableChannel和Selector等暴露给用户)。这在Windows和*nix上都是可能的。这是反应器模式。现在,JDK7引入了NIO.2 API,其中包括异步API(proactor模式),并使用内部(可配置的)线程池在后台进行IO操作,并在完成后回调到用户代码。它可能在Windows上使用IOCP,但我想知道: 1. 在我的主要平台Linux上,它使用什么?它使用epoll和friends,还是使用线程池来执行阻塞IO? 2. NIO.2中实际的IO操作(与平台无关)是由Java线程池中的用户线程执行,还是由内核线程执行,而Java线程池线程只负责复制字节缓冲区并回调给用户代码?
1个回答

8
如果检测到Linux内核版本>=2.6,则java.nio.channels.spi.SelectorProvider将使用epoll。
以下是Java 7中的DefaultSelectorProvider.java source代码片段:
public static SelectorProvider create() {
    String osname = AccessController.doPrivileged(
        new GetPropertyAction("os.name"));
    if ("SunOS".equals(osname)) {
        return new sun.nio.ch.DevPollSelectorProvider();
    }

    // use EPollSelectorProvider for Linux kernels >= 2.6
    if ("Linux".equals(osname)) {
        String osversion = AccessController.doPrivileged(
            new GetPropertyAction("os.version"));
        String[] vers = osversion.split("\\.", 0);
        if (vers.length >= 2) {
            try {
                int major = Integer.parseInt(vers[0]);
                int minor = Integer.parseInt(vers[1]);
                if (major > 2 || (major == 2 && minor >= 6)) {
                    return new sun.nio.ch.EPollSelectorProvider();
                }
            } catch (NumberFormatException x) {
                // format not recognized
            }
        }
    }

    return new sun.nio.ch.PollSelectorProvider();
}

NIO 2和“原始”的NIO 1都必须使用低级事件通知机制或Linux AIO API(相对较新),因为您永远不知道应用程序运行的机器上的内核是什么。我不会感到惊讶,如果看到NIO 2实际上使用Linux AIO或可能是POSIX AIO(它们非常不同)。


1
NIO.2 是否使用 SelectorProvider 呢? 我不太确定的是,NIO.2 中的异步实现在底层是否类似于 NIO 中通过 Epoll 进行准备检查的方式。或者它是使用一组执行阻塞 IO 的线程池来模拟异步操作的呢? - Ankur Kanoria
“模拟异步”?那里没有“模拟”,每个异步框架都使用抢占式(线程)或协作式多任务处理(纤程、协程、绿色线程)来实现异步处理。 - DejanLekic
1
据我所知,AsynchronousFileChannel 在池上执行阻塞同步文件读取,因此它不是真正的异步,而是模拟。另一方面,它对套接字进行选择,这是真正的异步 :) - Sergey Mashkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接