allocate比allocatedirect快得多,因前者在jvm堆内分配byte[]数组,仅纳秒级开销;后者需jni调用os分配堆外内存并注册cleaner,耗时高10–100倍。

创建缓冲区时,allocate 比 allocateDirect 快得多——这是确定的结论。根本原因在于内存分配层级不同:前者在 JVM 堆内完成,后者需通过 JNI 调用操作系统分配本地内存。
allocate 分配快,因为只走 JVM 内存路径
HeapByteBuffer 的分配本质是新建一个 byte[] 数组,由 JVM 在堆中快速划出连续空间,不涉及系统调用。整个过程接近纯 Java 对象创建,开销极小,通常在纳秒级完成。
- 适合高频、短生命周期场景,比如单次网络请求中的临时报文组装
- 容量越小,优势越明显;1KB 以下几乎无感知差异
- 无需手动管理,GC 自动回收底层数组
allocateDirect 分配慢,但使用阶段有补偿优势
DirectByteBuffer 需触发 JNI 进入 OS 层,在物理内存中申请页对齐的缓冲区,还要注册 Cleaner 清理钩子。单次分配耗时通常是 allocate 的 10–100 倍(微秒级),尤其在高并发批量创建时容易成为瓶颈。
- 分配慢 ≠ 总体慢:若该缓冲区被反复用于通道读写(如 Netty 的 IO 线程池长期持有),零拷贝收益会覆盖初始开销
- 避免 JVM 堆与内核空间之间的数据复制,对大块数据(≥64KB)传输提升显著
- 频繁创建/销毁 DirectBuffer 反而拖累性能,应复用而非每次 new
实测典型耗时参考(JDK 17,Linux x86_64)
基于千次循环创建 8KB 缓冲区的平均值:
-
ByteBuffer.allocate(8192):约 25–40 纳秒 -
ByteBuffer.allocateDirect(8192):约 1.2–3.5 微秒(即 1200–3500 纳秒) - 差距约 50–100 倍,且随容量增大,Direct 分配的绝对耗时增长更快
选型建议看使用模式,不看单点耗时
不要因“allocateDirect 分配慢”就回避它,关键看缓冲区是否复用:
- 一次性的解析/编码操作 → 用
allocate - 长连接中持续收发数据的 channel buffer → 用
allocateDirect并池化复用 - 不确定时先用
allocate,压测发现拷贝成瓶颈再切 Direct
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











