BIO/NIO/AIO 与多路复用

共 85 题
#

1. AIO 与 Netty 的边界

A AIO 只能用于文件读写,不能用于网络
B AIO 在 Linux 上基于 IOCP 实现,性能远优于 Netty 的 NIO
C AIO 是"同步非阻塞"模型,Netty 是"异步"模型
D Netty 基于 NIO 的 Selector 多路复用,在 Linux 上通常比原生 AIO 更受青睐 ✓ 正确答案
#

2. AIO 在 JDK 25 虚拟线程下的协作

A 虚拟线程必须依赖 AIO 才能实现高并发
B 虚拟线程只能在非阻塞 I/O 模型下工作
C AIO 在 JDK 25 中已被彻底移除
D 虚拟线程让阻塞式 I/O 变得廉价,多数网络场景可优先采用虚拟线程 + 阻塞式 I/O ✓ 正确答案
#

3. AIO(NIO.2 异步)模型与回调/Future

A AIO 是同步阻塞模型,调用后必须等待完成
B AIO 在 Linux 上基于 IOCP,在 Windows 上基于 epoll
C AIO 提供 CompletionHandler 回调与 Future 两种方式,I/O 完成后由内核通知 ✓ 正确答案
D Future 方式比回调方式更贴近异步事件驱动模型
#

4. BIO(Blocking I/O)的线程-连接 1:1 模型在 C10K 问题下的资源瓶颈

A 一万个连接对应一万个线程,栈内存和上下文切换开销巨大,导致资源耗尽 ✓ 正确答案
B BIO 的 1:1 模型可以用一个线程处理所有连接
C 解决 C10K 只能通过增加物理内存,与线程模型无关
D BIO 的主要瓶颈是 CPU 计算能力不足,而非线程资源
#

5. BIO(同步阻塞)模型与典型 one-connection-per-thread 模式

A 每个连接由独立线程处理,线程阻塞在读写上,连接多时线程资源耗尽 ✓ 正确答案
B 该模式用一个线程轮询处理所有连接
C 该模式天然支持高并发连接而无需额外资源
D BIO 是异步非阻塞模型,线程不会阻塞
#

6. Buffer 的核心属性(capacity/position/limit/mark)

A flip() 将 position 设为 limit,limit 设为 capacity
B clear() 会清空 Buffer 中的全部数据
C flip() 将 limit 设为 position、position 归零,用于从写模式切换为读模式 ✓ 正确答案
D capacity 在读取过程中会不断减小
#

7. CharBuffer/IntBuffer 的工程应用

A CharBuffer 与 IntBuffer 是独立的存储区,与 ByteBuffer 无关
B IntBuffer 只能用于像素数据,不能用于其他整型批量处理
C 通过 ByteBuffer.asCharBuffer()/asIntBuffer() 可创建类型化视图,共享底层字节 ✓ 正确答案
D CharBuffer 无法配合 CharsetEncoder 进行字符编码
#

8. CompletionStage 与 AIO 的整合

A 在 completed 中调用 future.complete,在 failed 中调用 future.completeExceptionally,从而把回调桥接为 CompletableFuture ✓ 正确答案
B AIO 无法与 CompletableFuture 整合,只能使用回调
C CompletableFuture 只能用于本地计算,不能包装 I/O 结果
D 在 AIO 回调的 completed 中调用 future.completeExceptionally,failed 中调用 complete
#

9. EpollSelectorImpl 在 Linux 6.x 内核下的 EPOLLEXCLUSIVE 模式是否被 JDK NIO 启用

A JDK NIO 默认必有多个线程同时 epoll_wait 同一 fd,必然使用 EPOLLEXCLUSIVE
B EPOLLEXCLUSIVE 用于放大惊群效应,唤醒所有等待线程
C EPOLLEXCLUSIVE 用于解决多线程共享 fd 时的惊群效应,只唤醒一个等待者 ✓ 正确答案
D EPOLLEXCLUSIVE 是 Windows 特有机制,与 epoll 无关
#

10. Files.copy/Files.move 在 JDK 25 中的 NIO.2 实现与原子操作语义

A Files.move 在任何情况下都是原子的
B Files.move 在同一文件系统内使用 rename 是原子的,跨文件系统时退化为复制+删除而非原子 ✓ 正确答案
C Files.copy 默认是原子操作
D ATOMIC_MOVE 选项在底层不支持时会被静默忽略
#

11. Future 模式在 AIO 的应用

A AIO 操作传入 null 的 CompletionHandler 时返回 Future,可阻塞等待结果或检查完成状态 ✓ 正确答案
B Future 模式与 CompletionHandler 不能同时使用,二者互斥
C AIO 操作返回的 Future.get() 会立即返回,从不阻塞
D AIO 的 Future 无法获取实际读写的字节数
#

12. JDK 25 虚拟线程与 Selector 阻塞(select pinning)问题的现状与官方建议

A Selector 阻塞会提高虚拟线程的吞吐能力
B pinning 问题只影响平台线程,与虚拟线程无关
C 虚拟线程阻塞在 Selector 上可能被钉住 carrier 线程,官方建议虚拟线程场景优先使用阻塞式 I/O ✓ 正确答案
D JDK 25 已彻底移除 Selector,无需担心 pinning
#

13. Java NIO 2.0 的 Path/Paths/Files 演进

A Files 只能用于读取,不能用于写入或删除
B Path 是旧 File 类的子类,功能完全相同
C Paths.get() 创建 Path,Files 提供静态文件操作,相对旧 File 类新增了符号链接/属性/监控等能力 ✓ 正确答案
D NIO 2.0 移除了文件系统提供者机制,只支持默认文件系统
#

14. Java NIO 的水平触发(Level-Triggered)本质

A 水平触发只在事件状态变化时报告一次,之后不再报告
B Java NIO 默认采用边缘触发,需要调用方手动设置
C 水平触发是边缘触发的别名,两者完全相同
D Java NIO 在 Linux 上默认使用水平触发,只要 fd 可读/可写就持续报告该事件 ✓ 正确答案
#

15. 零拷贝(Zero-Copy)在 Java 中的实现(FileChannel.transferTo)

A transferTo 需要把数据先拷贝到用户态再发送
B transferTo 会增加拷贝次数,性能更差
C transferTo 在 Linux 上基于 sendfile,由内核直接搬运文件到 socket,减少用户态拷贝 ✓ 正确答案
D transferTo 只能用于文件到文件,不能用于 socket
#

16. AIO 与 io_uring 提案的边界

A io_uring 是 Linux 新一代异步 I/O 接口,java AIO 在 Linux 上当前仍基于 epoll,尚未默认使用 io_uring ✓ 正确答案
B io_uring 只能在 Windows 上使用
C AIO 是内核接口,io_uring 是 JDK API
D Java AIO 在 Linux 上如今已默认使用 io_uring 作为底层
#

17. AIO 在 Linux 上基于 epoll 的实现

A AIO 在 Linux 上无法工作,只能用于 Windows
B AIO 在 Linux 上使用 IOCP 实现真正的异步 I/O
C AIO 在 Linux 上直接使用 io_uring,性能远超 NIO
D AIO 在 Linux 上通过 epoll 模拟异步,性能与 NIO 接近 ✓ 正确答案
#

18. AIO 的 AsynchronousChannelGroup 线程池如何配置,回调线程与业务线程池如何避免相互阻塞

A 应在回调线程中直接执行耗时业务逻辑以提高效率
B 回调线程只负责轻量结果传递,耗时业务应交给独立业务线程池,避免相互阻塞 ✓ 正确答案
C 回调线程与业务线程池必须共用同一个线程池
D AsynchronousChannelGroup 无法配置线程池大小
#

19. ByteBuffer 与 Netty ByteBuf 的差异

A ByteBuf 使用单一 position 指针,需要 flip 切换读写模式
B ByteBuf 使用独立的 readerIndex/writerIndex,支持动态扩容与池化,ByteBuffer 的单一 position 且容量固定 ✓ 正确答案
C ByteBuffer 支持动态扩容,ByteBuf 不支持
D 两者完全相同,只是命名不同
#

20. ByteBuffer 复用是否带来显著差异

A 复用 ByteBuffer 在任何场景下都毫无差别
B 直接缓冲区复用不会有任何收益,因为不受 GC 影响
C 高并发 I/O 下复用可减少分配与 GC 开销,直接缓冲区复用收益更明显,但需管理生命周期与线程安全 ✓ 正确答案
D ByteBuffer 不能被复用,每次必须新建
#

21. ByteBuffer 的 wrap 工厂

A wrap 只能用于直接缓冲区
B wrap 会复制数组内容到新分配的内存
C wrap 用已有数组作为底层存储,不拷贝,修改会反映到原数组 ✓ 正确答案
D wrap 创建的 buffer 无法被读写
#

22. ByteBuffer 的分散/聚集 I/O(ScatteringByteChannel)

A ScatteringByteChannel 通过 read(ByteBuffer[]) 一次系统调用读取数据到多个缓冲区 ✓ 正确答案
B 分散/聚集需要多次系统调用才能读写多个缓冲区
C 分散/聚集只在 Windows 上可用
D GatheringByteChannel 用于读取而非写入
#

23. ByteBuffer 的直接缓冲(Direct)与堆内缓冲

A Direct 缓冲内存在 JVM 堆内,受 GC 管理
B Direct 缓冲在堆外,I/O 时减少拷贝但分配开销大;Heap 缓冲在堆内,I/O 时通常有额外拷贝 ✓ 正确答案
C Heap 缓冲性能总是优于 Direct 缓冲
D Direct 缓冲受 -Xmx 堆大小限制
#

24. ByteBuffer.allocateDirect 的内存回收(Cleaner)

A DirectByteBuffer 通过基于 PhantomReference 的 Cleaner 在对象不可达后回收堆外内存,回收时机不确定 ✓ 正确答案
B Direct 内存不受 MaxDirectMemorySize 限制
C Direct 内存回收是确定性的,不依赖 GC
D DirectByteBuffer 的内存由 GC 直接回收,无需特殊机制
#

25. ByteBuffer.asXxxBuffer 的视图

A asXxxBuffer 只能用于直接缓冲区
B 视图缓冲会复制一份独立的数据
C 视图缓冲与字节序无关
D 视图缓冲与原始 ByteBuffer 共享底层数据,修改互相可见 ✓ 正确答案
#

26. DirectByteBuffer 的内存对齐与性能

A DirectByteBuffer 按页对齐分配,便于零拷贝、mmap 与 DMA 传输,减少性能退化 ✓ 正确答案
B 内存对齐会降低 I/O 性能,应避免
C 内存对齐只影响 Java 对象,与 I/O 无关
D DirectByteBuffer 从不进行内存对齐
#

27. FileChannel 在大文件拷贝的应用

A transferTo/transferFrom 基于 sendfile 实现零拷贝,适合大文件拷贝,但需注意单次 2GB 上限并循环调用 ✓ 正确答案
B FileChannel 无法拷贝大文件
C FileChannel 只能通过 read/write 循环拷贝,无性能优势
D transferTo 每次循环必须把数据读入用户态
#

28. FileChannel 的读写与 transferTo/transferFrom

A transferTo 经过用户态缓冲,适合处理数据内容
B transferTo 与 read 完全等价,无性能差异
C transferTo 只能用于文件到文件,不能复制到 socket
D read/write 经过用户态缓冲可处理数据,transferTo/transferFrom 零拷贝只适合纯搬运 ✓ 正确答案
#

29. FileChannel.force() 与持久化

A force() 相当于 fsync,将页缓存数据强制刷盘,确保持久化,但开销较大 ✓ 正确答案
B force() 什么都不做,write 已确保持久化
C force() 只影响文件大小,不影响数据内容
D force(true) 比 force(false) 开销更小
#

30. FileChannel.lock 与文件锁

A 文件锁用于 JVM 内多线程的互斥
B 文件锁在任何文件系统上都完全一致
C 进程崩溃后文件锁不会释放
D lock() 是阻塞式、tryLock() 是非阻塞式,文件锁用于跨进程协调,有共享/排他两种类型 ✓ 正确答案
#

31. FileChannel.map() 的内存映射文件(Memory-Mapped File)在随机读写场景的性能取舍

A 内存映射随机访问性能好,但持久化需主动 force,且映射占用地址空间、回收依赖 GC ✓ 正确答案
B 内存映射不占用地址空间,可无限映射
C 内存映射随机访问性能差,因为每次都要系统调用
D 内存映射写入会自动立即持久化,无需 force
#

32. JDK 25 中虚拟线程对 Selector 的 select/wakeup 调用阻塞的兼容性边界

A 虚拟线程不能调用 Selector 的任何方法
B 虚拟线程与 Selector 完全没有兼容性问题
C Selector 只能用于虚拟线程,不能用于平台线程
D 虚拟线程阻塞在 Selector.select 上可能钉住 carrier 线程,官方建议虚拟线程场景优先用阻塞式 I/O ✓ 正确答案
#

33. JDK 25 虚拟线程下 NIO Selector 的 wakeup 唤醒机制是否仍使用 Pipe 与 Selector.wakeup 内部竞争

A wakeup 会丢失事件,先 wakeup 后 select 不返回
B wakeup 基于 Pipe/self-pipe trick,先 wakeup 后 select 时下一次 select 会立即返回 ✓ 正确答案
C wakeup 在 JDK 25 中已被移除
D wakeup 只能由 Selector 的注册线程调用
#

34. Java NIO 在高并发下的边界(epoll 空轮询 bug)

A 空轮询 bug 只在 Windows 上出现
B 空轮询 bug 导致 CPU 100%,Netty 通过空转检测并重建 Selector 解决 ✓ 正确答案
C 空轮询 bug 会导致数据丢失,无法修复
D 空轮询 bug 与 Selector 无关
#

35. Java Selector 的就绪语义与 Linux epoll、macOS kqueue、Windows 实现差异应如何隔离测试

A 各平台 Selector 就绪语义完全一致,无需差异测试
B Selector 只在 Linux 上可用
C 就绪语义差异只影响性能,不影响正确性
D Linux 用 epoll、macOS 用 kqueue、Windows 用 select,就绪语义有差异,应抽象封装并在多平台 CI 测试 ✓ 正确答案
#

36. Linux epoll 与 JDK NIO Selector 的 epoll_ctl 系统调用映射细节

A epoll 用 epoll_create 注册事件,不使用 epoll_ctl
B JDK 的 OP_READ 直接映射到 EPOLLOUT
C JDK 通过 epoll_ctl 的 ADD/MOD/DEL 管理 fd 事件,修改 interestOps 对应 EPOLL_CTL_MOD ✓ 正确答案
D epoll_ctl 每次调用都不涉及系统调用
#

37. Linux epoll 的 LT/ET 模式与 Java Selector

A Java Selector 同时支持 LT 和 ET,可自由切换
B Java Selector 默认采用边缘触发(ET)
C Java Selector 在 Linux 上采用水平触发(LT),标准库不直接暴露 ET 模式 ✓ 正确答案
D ET 模式比 LT 更简单,Java 默认使用 ET
#

38. NIO Selector 在 Linux 下底层 epoll 与 macOS 下 kqueue 的可移植性边界

A Selector 统一抽象了 epoll/kqueue 差异,业务代码可移植,但底层行为(如空轮询 bug)仍因平台而异 ✓ 正确答案
B Selector 只能在 Linux 上使用,macOS 上不可用
C epoll 与 kqueue 事件语义完全一致,无任何差异
D Selector 在 macOS 上使用 epoll
#

39. NIO Selector 的 native 方法注册顺序是否影响启动

A native 方法注册顺序在正常启动下由 JDK 类加载保证,开发者无需担心,异常环境才可能出问题 ✓ 正确答案
B native 方法注册顺序错误会导致所有 Java 程序无法启动
C native 方法注册顺序必须由开发者手动控制
D NIO 不使用 native 方法,全用 Java 实现
#

40. NIO Selector 的 select(long) 与 selectNow() 在低流量场景下的 CPU 唤醒率差异如何用 JFR 量化

A selectNow() 在低流量下最省 CPU
B select(timeout) 在低流量下 CPU 占用最高
C selectNow() 在低流量下会空转抬高 CPU,应使用阻塞式 select(timeout),JFR 可量化 CPU 占用 ✓ 正确答案
D JFR 无法分析 CPU 占用
#

41. NIO Selector 的空轮询 bug 与 Netty 的解决

A Netty 通过检测空转次数并重建 Selector 迁移 Channel 来规避空轮询 bug ✓ 正确答案
B 空轮询 bug 无法解决,只能重启
C Netty 通过增加线程解决空轮询 bug
D 空轮询 bug 只影响 Windows 平台
#

42. NIO.2 与 Path 的 relativize/resolve

A resolve 与 relativize 功能完全相同
B resolve 只能处理绝对路径
C relativize 用于拼接路径,resolve 用于计算相对路径
D resolve 用于拼接路径,relativize 用于计算相对路径,二者互逆 ✓ 正确答案
#

43. NIO(同步非阻塞)模型与 Selector 多路复用

A NIO 是异步阻塞模型
B 单个线程通过 Selector 可监控多个通道,事件就绪后由线程执行读写,避免 BIO 的 1:1 线程模型 ✓ 正确答案
C Selector 每次只能监控一个通道
D NIO 每个连接仍需要一个独立线程
#

44. Netty EpollEventLoopGroup 与 JDK Selector

A EpollEventLoopGroup 基于 JDK Selector,与 NioEventLoopGroup 完全相同
B EpollEventLoopGroup 只能在 Windows 上使用
C EpollEventLoopGroup 不支持边缘触发
D EpollEventLoopGroup 基于原生 epoll,支持 ET 等特性并规避空轮询 bug,但仅适用 Linux ✓ 正确答案
#

45. Netty 与 JDK NIO 的边界

A Netty 只能用于简单网络场景
B Netty 完全替代了 JDK NIO,不依赖它
C JDK NIO 提供了完整的事件循环与编解码,无需 Netty
D Netty 是封装并增强 JDK NIO 的上层框架,提供 ByteBuf、编解码、Pipeline 等能力 ✓ 正确答案
#

46. ReadableByteChannel/WritableByteChannel 的接口语义

A read 永不返回 -1
B 这两个接口只能用于文件通道
C write 总是写入全部字节
D read 返回 -1 表示 EOF,write 返回实际写入字节数,ByteChannel 同时继承两者 ✓ 正确答案
#

47. Selector 与 EventLoop 是 1:1 还是 N:1

A 一个 Selector 被多个 EventLoop 共享(N:1)
B 每个 EventLoop 绑定一个线程和一个 Selector(1:1),保证通道访问在单线程内串行 ✓ 正确答案
C 一个 EventLoop 使用多个 Selector
D EventLoop 与 Selector 无关
#

48. Selector 与 kqueue(BSD/macOS)的关系

A kqueue 是 Linux 特有的机制
B macOS 上 Selector 使用 epoll
C Selector 与 kqueue 完全无关
D macOS 上 Selector 基于 kqueue 实现,通过 KQueueSelectorProvider 桥接 ✓ 正确答案
#

49. Selector 与虚拟线程结合使用时,单连接单线程模型下 fd 数量上限是否会突破传统 1024 文件描述符限制

A Selector 让一个 fd 管理多个连接,从而突破限制
B 虚拟线程自动突破 1024 文件描述符限制
C fd 上限由系统 ulimit 决定,虚拟线程或 Selector 不会自动突破,需提高系统 fd 限制 ✓ 正确答案
D fd 限制只存在于 Windows
#

50. Selector 在 CompletableFuture 链中的阻塞问题

A 在 CompletableFuture 回调中调用阻塞的 select 会占用并可能耗尽线程池线程,应放到专门 I/O 线程执行 ✓ 正确答案
B 在 CompletableFuture 中调用 select 完全无风险
C CompletableFuture 回调不会受阻塞影响
D select 不是阻塞方法
#

51. Selector 在 JDK 25 虚拟线程下的协作

A 虚拟线程场景官方建议优先用阻塞式 I/O,Selector 多路复用非其推荐场景,select 阻塞可能引发 pinning ✓ 正确答案
B Selector 在虚拟线程下无任何问题
C 虚拟线程必须使用 Selector 才能高并发
D 虚拟线程不能使用 Selector
#

52. Selector 在 Windows 上的实现差异

A Windows 上 Selector 基于 IOCP
B Windows 上 Selector 与 Linux 完全一致
C Windows 不支持 Selector
D Windows 上默认 Selector 基于 select 模型,AIO 才用 IOCP,与 epoll/kqueue 行为有差异 ✓ 正确答案
#

53. Selector 在高并发下的 epoll 性能

A 单 Selector 线程永远够用,无瓶颈
B epoll 在高并发下性能劣于 select
C epoll 事件驱动高效,但单 Selector 线程、interestOps 更新与事件处理耗时是瓶颈,可用多事件循环与业务线程池优化 ✓ 正确答案
D 高并发下应禁用 epoll
#

54. Selector 报告可读只表示读取可能推进,非阻塞 read 返回零或负一时分别应如何处理

A 可读事件一定意味着能读到数据
B 可读事件只表示读取可能推进,read 返回 0 表示无数据继续等待,-1 表示对端关闭应处理 EOF ✓ 正确答案
C read 返回 0 表示连接关闭
D read 返回 -1 表示有更多数据
#

55. Selector 的 select/selectedKeys 流程

A selectedKeys 会自动清理,无需手动移除
B select 返回后 selectedKeys 永久有效
C 不需要遍历 selectedKeys,直接处理所有通道
D 遍历 selectedKeys 处理就绪事件后必须用 iterator.remove() 移除,否则会重复处理 ✓ 正确答案
#

56. Selector 的关闭与资源释放

A Selector 无需主动关闭
B close() 释放 fd 并使已注册 key 失效,应配合通道关闭,用 try-with-resources 管理 ✓ 正确答案
C 关闭 Selector 会同时关闭所有通道
D 关闭 Selector 不会让 key 失效
#

57. Selector 的核心 API(open/register/select)

A register() 是 Selector 的方法,用于创建通道
B open() 创建 Selector,register() 注册通道并指定兴趣操作,select() 阻塞等待就绪 ✓ 正确答案
C select() 是非阻塞的,永远立即返回
D open() 不需任何底层资源
#

58. Selector 资源是否应在模块销毁时主动 close 避免 fd 泄漏

A Selector 不占用 fd,无需关闭
B 模块销毁时应主动 close() Selector 并配合关闭通道,避免 fd 泄漏 ✓ 正确答案
C 关闭 Selector 与 fd 无关
D 框架关闭 Selector 后,业务代码无需再关心通道
#

59. Selector.select() 与 selectNow()/select(timeout) 的差异

A select() 无限阻塞、selectNow() 非阻塞立即返回、select(timeout) 超时阻塞,适用场景不同 ✓ 正确答案
B selectNow() 会阻塞等待事件
C 三者完全相同
D select(timeout) 永不阻塞
#

60. Selector.wakeup 的调用可以合并意味着什么,先 wakeup 后 select 的下一次阻塞行为如何定义

A 先 wakeup 后 select 时 select 仍会阻塞
B 多次 wakeup 会产生多次唤醒副作用
C wakeup 可合并(多次等价一次),先 wakeup 后 select 时下一次 select 会立即返回 ✓ 正确答案
D wakeup 只能由 select 线程调用
#

61. Selector.wakeup() 的实现原理

A wakeup 通过修改注册事件实现
B wakeup 直接中断 select 线程
C wakeup 通过 self-pipe trick 向内部管道写入字节使 select 返回,并配合唤醒标志 ✓ 正确答案
D wakeup 只能由 select 线程调用
#

62. SocketChannel 的连接、OP_CONNECT 与 finishConnect

A 非阻塞 connect 总是立即完成
B 非阻塞 connect 返回 false 表示连接进行中,需注册 OP_CONNECT,就绪后调用 finishConnect 确认结果 ✓ 正确答案
C OP_CONNECT 就绪后无需调用 finishConnect
D finishConnect 永远不会抛异常
#

63. SocketChannel 部分写入后为何只应在仍有待发数据时注册 OP_WRITE,否则会造成怎样的空转

A 应始终注册 OP_WRITE 以保持高吞吐
B OP_WRITE 就绪后不会重复触发
C OP_WRITE 与 OP_READ 不能同时注册
D 只在仍有待发数据时注册 OP_WRITE,写完取消,否则 socket 可写会持续触发 OP_WRITE 造成空转 ✓ 正确答案
#

64. SocketChannel/ServerSocketChannel 的非阻塞配置与 Selector 协作模式

A 非阻塞通道无法注册到 Selector
B 服务端 accept 得到的连接会自动阻塞
C 非阻塞配置只影响读写,不影响连接
D 通道 configureBlocking(false) 后注册到 Selector,通过 OP_ACCEPT/OP_CONNECT/OP_READ/OP_WRITE 事件驱动高并发 ✓ 正确答案
#

65. TLS 使用 SSLEngine 叠加 Selector 时,握手状态、网络缓冲和应用缓冲如何驱动兴趣事件

A SSLEngine 的 NEED_UNWRAP 时注册 OP_READ,NEED_WRAP 且有输出时注册 OP_WRITE,由握手状态驱动 ✓ 正确答案
B SSLEngine 与 Selector 无关,无需驱动事件
C 握手时只注册 OP_WRITE
D NEED_TASK 表示需要注册 OP_READ
#

66. Windows IOCP 与 AIO 的实现差异

A Windows 上 AIO 基于 epoll
B IOCP 只用于 Linux
C Windows 上 AIO 基于 IOCP 实现真正的内核异步 I/O,与 Linux 基于 epoll 模拟异步不同 ✓ 正确答案
D AIO 在 Windows 上不使用任何异步机制
#

67. java.util.concurrent.Future 与 AIO 的差异

A 两者完全相同
B 并发 Future 由任务完成,AIO Future 由内核 I/O 完成,且 AIO 额外支持 CompletionHandler 回调 ✓ 正确答案
C AIO 的 Future 不支持 get()
D 并发 Future 支持回调
#

68. 从其他线程修改 interestOps 或注册 Channel 时,如何配合任务队列与 wakeup 避免更新延迟

A 可直接在其他线程修改 SelectionKey
B 提交任务后无需 wakeup
C 应封装为任务提交到事件循环线程队列并调用 wakeup 唤醒,保证串行执行避免延迟 ✓ 正确答案
D 事件循环线程会自动感知任务无需唤醒
#

69. 使用 JDK Flight Recorder 分析 NIO Selector 空轮询 bug(CPU 100%)

A 空轮询 bug 无法用 JFR 诊断
B JFR 无法分析 CPU 占用
C 通过 JFR 的 CPU 采样事件(jdk.ExecutionSample)生成火焰图,定位 Selector.select 循环的空转热点 ✓ 正确答案
D JFR 只能分析内存,不能分析 CPU
#

70. 使用 Selector 注册 OP_CONNECT 与 OP_WRITE 时,连接成功前的多次可写事件应如何避免 busy-loop

A 连接前就应注册 OP_WRITE 以尽早发送
B OP_CONNECT 与 OP_WRITE 不会同时触发
C 连接成功前只注册 OP_CONNECT,连接完成后再注册 OP_WRITE,避免连接过程中的可写事件造成 busy-loop ✓ 正确答案
D 连接过程中注册 OP_WRITE 不会造成空转
#

71. 发生疑似空轮询时,重建 Selector 并迁移 Channel 需要保持哪些注册状态和并发顺序

A 只需迁移 Channel,无需恢复 interestOps
B 迁移需恢复每个 Channel 的 interestOps 与 attachment,并在事件循环线程内单线程完成避免并发竞争 ✓ 正确答案
C 重建可在任意线程完成
D 迁移后无需关闭旧 Selector
#

72. 同一 Channel 为什么不能注册到已关闭 Selector,关闭顺序如何避免文件描述符与任务泄漏

A 已关闭 Selector 仍可注册 Channel
B 已关闭 Selector 注册会抛 ClosedSelectorException,应先关闭通道再关 Selector 以避免 fd 泄漏 ✓ 正确答案
C 应先关闭 Selector 再关闭 Channel
D 关闭顺序不影响资源释放
#

73. 每连接独占大 ByteBuffer 会造成什么直接内存压力,缓冲池与动态扩容如何避免数据串扰

A 直接缓冲受 -Xmx 限制,不会溢出
B 每连接独占大缓冲无内存压力
C 缓冲池复用不会产生数据串扰
D 每连接独占大缓冲会造成巨大直接内存压力,缓冲池/动态扩容缓解但需复位与所有权管理避免数据串扰 ✓ 正确答案
#

74. 虚拟线程下多个业务线程共享同一个 Selector 是否仍需 synchronized 保护 selectedKeys 集合

A 虚拟线程自动使 selectedKeys 线程安全
B 虚拟线程下无需任何同步
C selectedKeys 集合非线程安全,虚拟线程下多线程共享仍需 synchronized 或单线程化处理 ✓ 正确答案
D 虚拟线程不能共享 Selector
#

75. 虚拟线程阻塞式套接字与单线程 Selector 模型各适合什么负载,不能仅按连接数判断的原因是什么

A 不能说仅按连接数判断,还需考虑数据活跃度、吞吐、延迟,二者各有适配负载 ✓ 正确答案
B 虚拟线程总是优于 Selector
C 连接数越多越适合单线程 Selector
D 单线程 Selector 适合大量低活跃连接
#

76. ByteBuffer 的 slice() 与数据共享

A slice() 会复制一份独立数据
B slice() 与原始 buffer 完全无关
C slice() 创建共享底层数据的子视图,具有独立 position/limit 但零拷贝 ✓ 正确答案
D slice() 只能用于直接缓冲区
#

77. JDK 25 NIO 2 的内部清理

A 通道关闭后 fd 仍保留
B NIO 2 资源只能由手动 close 管理,无兜底
C Cleaner 只负责堆内对象回收
D NIO 2 通过 Cleaner 回收直接内存、close 释放通道/Selector/WatchService 的 fd 等资源 ✓ 正确答案
#

78. JDK 25 中 Selector.select 方法在 G1 暂停期间是否被阻塞,导致长尾延迟超出预期

A GC 暂停不影响 Selector
B G1 STW 暂停冻结所有线程包括阻塞的 select,导致长尾延迟,可调优 GC 缓解 ✓ 正确答案
C select 在 GC 期间正常工作
D 长尾延迟与 GC 完全无关
#

79. Selector 与 io_uring 的未来(JDK 25+ 提案)

A JDK 25 已默认使用 io_uring
B io_uring 与 Selector 无关
C io_uring 是高性能 I/O 未来方向,JDK 有相关提案但截至 JDK 25 尚未默认落地,仍用 epoll ✓ 正确答案
D epoll 已被彻底移除
#

80. ServerSocketChannel 的 accept() 与 OP_ACCEPT

A OP_ACCEPT 就绪后应继续阻塞等待
B accept() 返回的通道无需配置非阻塞
C OP_ACCEPT 用于表示可写
D OP_ACCEPT 就绪表示有新连接可接受,此时 accept() 返回 SocketChannel 并注册读写 ✓ 正确答案
#

81. NIO Channel 接口层次与阻塞/非阻塞读写模型

A Channel 有可读/可写/分散/聚集等接口,网络通道支持非阻塞+Selector,FileChannel 不支持非阻塞 ✓ 正确答案
B 所有 Channel 都支持非阻塞
C 只有 FileChannel 支持 Selector
D Channel 是单一接口,无层次
#

82. JDK 25 中 KQueueSelectorProvider 在 macOS 上的兼容性与 NIO 可移植性测试

A KQueueSelectorProvider 只在 Linux 上可用
B KQueueSelectorProvider 在 macOS 上提供 Selector 标准语义,可移植性测试需多平台 CI 与平台无关断言 ✓ 正确答案
C NIO 无需跨平台测试
D 可移植性测试只在一台机器运行
#

83. Selector.open() 的 epoll fd 创建时机与文件描述符资源治理

A open() 即创建 epoll fd 直到 close 释放,需及时关闭并监控数量避免 fd 泄漏 ✓ 正确答案
B epoll fd 会自动释放无需关闭
C open() 不创建任何 fd
D fd 资源无需治理
#

84. ByteBuffer 与 GraalVM Native Image 的边界

A ByteBuffer 在 Native Image 中 Cleaner、反射、JNI 等机制与标准 JVM 有差异,需配置与验证 ✓ 正确答案
B Native Image 与标准 JVM 的 ByteBuffer 行为完全一致
C ByteBuffer 与 Native Image 无关
D ByteBuffer 在 Native Image 中完全不可用
#

85. JDK 25 中 ServerSocketChannel 配置为非阻塞模式的方法(configureBlocking(false))

A 非阻塞配置后 accept() 会阻塞等待
B configureBlocking(false) 使通道非阻塞、可注册 Selector,阻塞通道不能注册到 Selector ✓ 正确答案
C 阻塞通道可以直接注册到 Selector
D configureBlocking(false) 与 Selector 无关