转换UUID与BigInteger时遇BufferUnderflowException及测试报错原因咨询
UUID与BigInteger互转时BufferUnderflowException异常解析
嘿,这个问题我帮不少开发者排查过,咱们一步步把它说透~
为什么会抛出BufferUnderflowException?
这个异常的核心原因很简单:你试图从ByteBuffer中读取的字节数,超过了它当前剩余的可读字节数。UUID是固定的128位(16字节),如果转换过程中字节数组长度不匹配、ByteBuffer容量不足,或者读取操作没有对应上实际的字节量,就会触发这个异常。
常见的错误测试场景
先看看你大概率写了类似这样的错误代码:
错误示例1:UUID转BigInteger时ByteBuffer容量不足
@Test public void testUuidToBigIntegerWrong() { UUID uuid = UUID.randomUUID(); // 这里只分配了8字节,UUID需要16字节存储! ByteBuffer buffer = ByteBuffer.allocate(8); buffer.putLong(uuid.getMostSignificantBits()); buffer.putLong(uuid.getLeastSignificantBits()); // 这里其实已经超出buffer容量了 buffer.flip(); // 试图读取16字节,但buffer里实际只有8字节,直接抛异常 byte[] bytes = new byte[16]; buffer.get(bytes); BigInteger bigInt = new BigInteger(bytes); }
错误示例2:BigInteger转UUID时字节数组长度不够
@Test public void testBigIntegerToUuidWrong() { BigInteger bigInt = new BigInteger("123456789"); // 这个数的字节数远小于16 byte[] bytes = bigInt.toByteArray(); ByteBuffer buffer = ByteBuffer.wrap(bytes); // 试图读取两个long(共16字节),但buffer里字节不足,抛出异常 long most = buffer.getLong(); long least = buffer.getLong(); UUID uuid = new UUID(most, least); }
正确的互转实现
要解决这个问题,核心就是保证转换过程中始终使用16字节的容器,处理好字节不足时的补0操作:
1. UUID转BigInteger
public BigInteger uuidToBigInteger(UUID uuid) { ByteBuffer buffer = ByteBuffer.allocate(16); // 固定16字节容量 buffer.putLong(uuid.getMostSignificantBits()); buffer.putLong(uuid.getLeastSignificantBits()); buffer.flip(); // 用第一个参数1确保生成正整数,避免符号位干扰 return new BigInteger(1, buffer.array()); }
2. BigInteger转UUID
public UUID bigIntegerToUuid(BigInteger bigInt) { byte[] rawBytes = bigInt.toByteArray(); ByteBuffer buffer = ByteBuffer.allocate(16); // 如果BigInteger的字节数组长度小于16,前面补0填充到16字节 if (rawBytes.length < 16) { buffer.put(new byte[16 - rawBytes.length]); } buffer.put(rawBytes); buffer.flip(); long mostSignificant = buffer.getLong(); long leastSignificant = buffer.getLong(); return new UUID(mostSignificant, leastSignificant); }
关键注意点
- UUID是128位固定长度,所以转换时必须保证容器(ByteBuffer/字节数组)是16字节,否则读取时必然字节不足
BigInteger.toByteArray()会省略前面的0,所以转UUID时必须补0到16字节,否则ByteBuffer读取两个long时会报错- 用
new BigInteger(1, bytes)可以避免符号位导致的负数问题,确保生成的BigInteger是正的,和UUID的无符号特性匹配
内容的提问来源于stack exchange,提问作者4ntoine
相关产品推荐
相关产品推荐

