当前位置: 首页 > news >正文

Java 异常处理之 BufferUnderflowException(BufferUnderflowException 概述、常见发生场景、避免策略)

一、BufferUnderflowException 概述

  1. BufferUnderflowException 是 Java NIO 包中的一个运行时异常,是 RuntimeException 的子类
public class BufferUnderflowException extends RuntimeException {...
}
# 继承关系java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> java.lang.RuntimeException-> java.nio.BufferUnderflowException
  1. 它发生在尝试从缓冲区读取比实际剩余更多的数据时,即缓冲区位置(position)已经到达或超过限制(limit)

二、常见发生场景

  1. 读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());int i1 = byteBuffer.getInt();// 读取 4 字节没问题
System.out.println("第 1 次读取:" + i1);
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());int i2 = byteBuffer.getInt();// 再读取 4 字节没问题
System.out.println("第 2 次读取:" + i2);
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());int i3 = byteBuffer.getInt(); // 再读取 4 字节,会抛出 BufferUnderflowException 异常
System.out.println("第 3 次读取:" + i3);
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
# 输出结果初始化
pos=0, remaining=10, limit=10
第 1 次读取:0
pos=4, remaining=6, limit=10
第 2 次读取:0
pos=8, remaining=2, limit=10
Exception in thread "main" java.nio.BufferUnderflowException
  1. 批量读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byte[] bytes = new byte[15];
byteBuffer.get(bytes);
System.out.println("读取数据:" + new String(bytes));
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
# 输出结果初始化
pos=0, remaining=10, limit=10
Exception in thread "main" java.nio.BufferUnderflowException
  1. 调用 flip 方法后,(批量)读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());String data = "abc";
byteBuffer.put(data.getBytes());
System.out.println("添加数据:" + data);
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byteBuffer.flip();
System.out.println("调用 flip 方法");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byte[] bytes1 = new byte[2];
byteBuffer.get(bytes1);
System.out.println("第 1 次读取:" + new String(bytes1));
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byte[] bytes2 = new byte[2];
byteBuffer.get(bytes2);
System.out.println("第 2 次读取:" + new String(bytes2));
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
# 输出结果初始化
pos=0, remaining=10, limit=10
添加数据:abc
pos=3, remaining=7, limit=10
调用 flip 方法
pos=0, remaining=3, limit=3
第 1 次读取:ab
pos=2, remaining=1, limit=3
Exception in thread "main" java.nio.BufferUnderflowException

三、避免策略

1、基本介绍
  1. 总是调用 remaining 方法检查剩余数据是否足够,不同的读取方法对读取长度有不同的要求
方法读取长度(字节)
byte get()1
char getChar()2
short getShort()2
int getInt()4
long getLong()8
float getFloat()4
double getDouble()8
ByteBuffer get(byte[] dst)dst.length
  1. 必要时,也可以通过 try catch 捕获异常
2、演示
  1. 读取数据(调用 remaining 方法检查)
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());int num = 1;
while (true) {if (byteBuffer.remaining() >= 4) {int i1 = byteBuffer.getInt();System.out.println("第 " + num + " 次读取:" + i1);System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());num++;} else {System.out.println("第 " + num + " 次读取");System.out.println("数据不足,无法读取");break;}
}
# 输出结果初始化
pos=0, remaining=10, limit=10
第 1 次读取:0
pos=4, remaining=6, limit=10
第 2 次读取:0
pos=8, remaining=2, limit=10
第 3 次读取
数据不足,无法读取
  1. 批量读取数据(调用 remaining 方法检查)
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byte[] bytes = new byte[15];
if (byteBuffer.remaining() < bytes.length) {System.out.println("数据不足,无法读取");
} else {byteBuffer.get(bytes);System.out.println("读取数据:" + new String(bytes));System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
}
# 输出结果初始化
pos=0, remaining=10, limit=10
数据不足,无法读取
  1. 调用 flip 方法后,(批量)读取数据(调用 remaining 方法检查)
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());String data = "abc";
byteBuffer.put(data.getBytes());
System.out.println("添加数据:" + data);
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byteBuffer.flip();
System.out.println("调用 flip 方法");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());byte[] bytes1 = new byte[2];
if (byteBuffer.remaining() < bytes1.length) {System.out.println("第 1 次读取");System.out.println("数据不足,无法读取");
} else {byteBuffer.get(bytes1);System.out.println("第 1 次读取:" + new String(bytes1));System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
}byte[] bytes2 = new byte[2];
if (byteBuffer.remaining() < bytes2.length) {System.out.println("第 2 次读取");System.out.println("数据不足,无法读取");
} else {byteBuffer.get(bytes2);System.out.println("第 2 次读取:" + new String(bytes2));System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
}
# 输出结果初始化
pos=0, remaining=10, limit=10
添加数据:abc
pos=3, remaining=7, limit=10
调用 flip 方法
pos=0, remaining=3, limit=3
第 1 次读取:ab
pos=2, remaining=1, limit=3
第 2 次读取
数据不足,无法读取
  1. 通过 try catch 捕获异常
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println("初始化");
System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());try {byte[] bytes = new byte[15];byteBuffer.get(bytes);System.out.println("读取数据:" + new String(bytes));System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
} catch (BufferUnderflowException e) {e.printStackTrace();System.out.println("读取数据失败");System.out.println("pos=" + byteBuffer.position() + ", remaining=" + byteBuffer.remaining() + ", limit=" + byteBuffer.limit());
}
# 输出结果初始化
pos=0, remaining=10, limit=10
java.nio.BufferUnderflowException
读取数据失败
pos=0, remaining=10, limit=10

相关文章:

  • C 语言学习笔记(8)
  • 因果推断 | 用SHAP分值等价因果效应值进行反事实推理
  • 【Linux】掌握 setsid:让进程脱离终端独立运行
  • 东芝新四款产品“TB67Z830SFTG、TB67Z830HFTG、TB67Z850SFTG、TB67Z850HFTG系列三相栅极驱动器ic三相栅极驱动器IC
  • 软件测试--入门
  • 【Linux】Ext系列文件系统
  • 鸿蒙-5.1.0-release构建编译环境
  • Oracle中的select1条、几条、指定范围的语句
  • 每日算法-250514
  • 【golang】网络数据包捕获库 gopacket
  • 嵌入式系统中WAV音频文件格式详解与处理实践
  • 【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】
  • Lightpanda开源浏览器:专为 AI 和自动化而设计的无界面浏览器
  • 安卓基础(Bitmap)
  • scons user 3.1.2
  • C#强类型枚举的入门理解
  • C++【STL】(2)string
  • 4级流程控制
  • 复现:DemoGen 用于数据高效视觉运动策略学习的 合成演示生成 (RSS) 2025
  • Docker 常见问题及其解决方案
  • 泽连斯基启程前往土耳其
  • 为何选择上海?两家外企提到营商环境、人才资源……
  • 中欧金融工作组第二次会议在比利时布鲁塞尔举行
  • 被前男友泼汽油致残后,一个女孩经历的双重灼烧
  • 国际能源署:全球电动汽车市场强劲增长,中国市场继续领跑
  • 北斗专访|特赞科技范凌:现在AI主要是“说话”,接下来要“干活”了