Objects.checkFromIndexSize()专为批量操作的起始索引和长度联合校验设计,通过无溢出算法避免整数溢出与逻辑错误,确保System.arraycopy、NIO等场景的安全性。
java 9 引入的 objects.checkfromindexsize() 是专为防御性边界检查设计的工具方法,特别适合在涉及数组、bytebuffer、unsafe 或大规模内存拷贝(如 system.arraycopy、arrays.copyofrange、nio 批量操作)前,**一次性验证起始索引和长度是否合法**,避免因手动计算导致的整数溢出或逻辑错误。
为什么不用手写 if (fromIndex array.length || size array.length)?
手动检查存在两个隐蔽风险:
-
整数溢出:当
fromIndex和size都很大(例如接近Integer.MAX_VALUE),fromIndex + size可能溢出为负数,使> array.length判断失效; - 逻辑冗余与易错:需同时检查下界、上界、非负性、和溢出安全的上界,代码易漏、难读、难复用。
Objects.checkFromIndexSize() 内部采用无溢出算法(如先比较 size > array.length - fromIndex),天然规避溢出问题,且抛出明确的 IndexOutOfBoundsException,消息含具体参数值,利于调试。
典型场景:保护 System.arraycopy 调用
这是最常见也最危险的场景——直接操作底层内存块时,越界可能导致 JVM 崩溃(尤其配合 Unsafe)或静默数据损坏。
// ✅ 安全做法:先校验,再拷贝
public static void safeCopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) {
Objects.checkFromIndexSize(srcPos, length, src.length); // 检查 src 范围
Objects.checkFromIndexSize(destPos, length, dest.length); // 检查 dest 范围
System.arraycopy(src, srcPos, dest, destPos, length);
}注意:必须**分别对源和目标独立校验**,因为二者长度不同、索引空间独立。
立即学习“Java免费学习笔记(深入)”;
进阶用法:适配 NIO ByteBuffer 批量读写
NIO 的 get(byte[] dst, int offset, int length) 等方法本身已做检查,但若你在自定义协议解析中手动计算切片(如从 ByteBuffer 中提取某段字节到新数组),仍需主动防护:
// ✅ 解析固定头后读取 payload
public static byte[] readPayload(ByteBuffer buffer, int headerLen, int payloadLen) {
int start = headerLen;
// 校验 buffer 是否足够容纳 payload(从 start 开始取 payloadLen 字节)
Objects.checkFromIndexSize(start, payloadLen, buffer.limit()); // limit 即有效上限
byte[] payload = new byte[payloadLen];
buffer.position(start);
buffer.get(payload);
return payload;
}关键点:checkFromIndexSize(from, size, bound) 中的 bound 应传入目标容器的**可访问上限**(如数组长度、ByteBuffer.limit()、List.size()),而非容量(capacity)。
与 Objects.requireNonNull 和 Objects.checkIndex 的分工
三者定位清晰,不替代:
-
requireNonNull:防空指针,不处理数值边界; -
checkIndex:只校验单个索引(如list.get(i)),不涉及长度; -
checkFromIndexSize:专治“起始+长度”二元组,是批量操作的守门员。
不要用 checkIndex(from + size - 1) 替代——它无法防止 from + size 溢出,也不表达语义意图。


















