Java中如何优雅地处理BufferUnderflowException异常?

部署运行你感兴趣的模型镜像

Java中如何优雅地处理BufferUnderflowException异常?

大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!

在Java编程中,BufferUnderflowException异常是一个常见的异常,通常在操作缓冲区时尝试读取超过缓冲区容量的数据时抛出。本文将介绍BufferUnderflowException异常的成因以及如何优雅地处理这个异常。

了解BufferUnderflowException异常

在处理BufferUnderflowException异常之前,首先需要了解它的成因。这个异常通常发生在使用缓冲区进行数据操作时,当试图从空缓冲区中读取数据或者尝试读取超过缓冲区容量的数据时,就会抛出这个异常。

处理BufferUnderflowException异常的方法

  1. 检查缓冲区的剩余数据
    在从缓冲区读取数据之前,始终检查缓冲区中是否还有剩余数据可供读取。可以使用hasRemaining()方法来检查缓冲区是否还有剩余数据,以避免读取超过缓冲区容量的数据而导致异常。

  2. 设置正确的读取位置
    确保在从缓冲区读取数据之前,设置正确的读取位置。通过调用flip()方法或rewind()方法来设置读取位置,确保读取操作从缓冲区的正确位置开始。

  3. 使用合适的读取方法
    使用合适的读取方法来读取缓冲区中的数据,避免使用不适当的读取方法导致异常。例如,使用get()方法来读取单个字节,使用get(byte[])方法来读取一组字节。

代码示例

下面是一些代码示例,演示了如何优雅地处理BufferUnderflowException异常:

import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;

public class BufferUnderflowExceptionExample {

    public static void main(String[] args) {
        // 创建一个容量为10的ByteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(10);

        try {
            // 尝试从空缓冲区中读取数据
            byte b = buffer.get();
        } catch (BufferUnderflowException e) {
            // 捕获BufferUnderflowException异常并进行处理
            System.err.println("BufferUnderflowException caught: Buffer is empty.");
        }
    }
}

在上面的示例中,我们尝试从一个空的ByteBuffer中读取数据,这将导致BufferUnderflowException异常被抛出。

总结

在处理Java中的BufferUnderflowException异常时,最重要的是要对缓冲区的状态进行有效管理,以确保在读取数据时不会超出缓冲区的容量。通过检查剩余数据、设置正确的读取位置和使用合适的读取方法,可以有效地预防和处理这种异常,保障程序的稳定性和可靠性。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

package com.tplink.smb.component.cache.ohc.serializer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import com.esotericsoftware.kryo.io.ByteBufferOutput; import net.jpountz.lz4.LZ4Compressor; import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4FastDecompressor; import org.caffinitas.ohc.CacheSerializer; import com.tplink.smb.component.cache.ohc.dto.Wrapper; /** * Description of this file * * @author Peng Xiaogang * @version 1.0 * @since 2025/9/25 */ public class CompressdKryoSerializer<T> implements CacheSerializer<Wrapper<T>> { private final LZ4Compressor compressor; private final LZ4FastDecompressor decompressor; public CompressdKryoSerializer() { LZ4Factory factory = LZ4Factory.fastestInstance(); this.compressor=factory.highCompressor(17); this.decompressor=factory.fastDecompressor(); } @Override public void serialize(Wrapper<T> value, ByteBuffer buf) { // 创建一个 ByteBufferOutput 对象,用于将数据写入 ByteBuffer ByteBufferOutput output = new ByteBufferOutput(buf); // 使用 Kryo 序列化 Wrapper 对象 byte[] bytes = KryoUtil.writeToByteArray(value); int originalLength = bytes.length; int maxCompressedLength = compressor.maxCompressedLength(originalLength); byte[] compressed = new byte[maxCompressedLength]; int compressedLength = compressor.compress(bytes, 0, originalLength, compressed, 0); output.writeInt(compressedLength); output.writeInt(originalLength); output.write(compressed,0,compressedLength); output.flush(); } @Override public Wrapper<T> deserialize(ByteBuffer buf) { // 检查是否有足够字节读取两个整数 if (buf.remaining() < 8) { throw new RuntimeException("Buffer underflow: not enough data for header"); } // 1. 显式设置字节序为大端模式(确保跨平台一致性) buf.order(ByteOrder.BIG_ENDIAN); // 引用[1] // 2. 读取压缩数据长度和原始数据长度 int compressedSize = buf.getInt(); int originalSize = buf.getInt(); // 检查是否有足够字节读取压缩数据 if (buf.remaining() < compressedSize) { throw new RuntimeException("Buffer underflow: not enough data for compressed body"); } // 3. 准备压缩数据和目标缓冲区 byte[] compressedData = new byte[compressedSize]; buf.get(compressedData); // 从缓冲区复制压缩数据 // 4. 执行LZ4解压缩 byte[] decompressedData = new byte[originalSize]; int decompressedBytes = decompressor.decompress( compressedData, 0, decompressedData, 0, originalSize ); // // 5. 验证解压完整性 // if (decompressedBytes != originalSize) { // throw new IllegalStateException("解压缩失败: 期望长度=" + originalSize + ", 实际长度=" + decompressedBytes); // } Object o = KryoUtil.readFromByteArray(decompressedData); return (Wrapper<T>) o; } @Override public int serializedSize(Wrapper<T> value) { byte[] bytes = KryoUtil.writeToByteArray(value); int originalLength = bytes.length; int maxCompressedLength = compressor.maxCompressedLength(originalLength); byte[] compressed = new byte[maxCompressedLength]; int compressedSize = compressor.compress(bytes, 0, originalLength, compressed, 0); return 8+compressedSize; } } public class KryoUtil { private static final String DEFAULT_ENCODING = "UTF-8"; private static final Pool<Kryo> pool = new Pool<Kryo>(true, false, 8) { @Override protected Kryo create() { Kryo kryo = new Kryo(); /** * 不要轻易改变这里的配置!更改之后,序列化的格式就会发生变化, * 上线的同时就必须清除所有缓存, * 否则那些缓存再回来反序列化的时候,就会报错 */ //支持对象循环引用(否则会栈溢出) kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置 //不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册) kryo.setRegistrationRequired(true);//默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置 /** * 注册需要序列化的类 */ kryo.register(List.class); kryo.register(ArrayList.class); kryo.register(Map.class); kryo.register(HashMap.class); kryo.register(Wrapper.class); kryo.register(HashSet.class); kryo.register(ConcurrentHashMap.class); kryo.register(TreeMap.class); kryo.register(LinkedHashMap.class); kryo.register(LinkedHashSet.class); kryo.register(ConcurrentHashMap.KeySetView.class); kryo.register(AtomicLong.class, new AtomicLongSerializer()); //Fix the NPE bug when deserializing Collections. ((DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy()) .setFallbackInstantiatorStrategy(new StdInstantiatorStrategy()); return kryo; } }; /** * 获得当前线程的 Kryo 实例 * * @return 当前线程的 Kryo 实例 */ public static Kryo getInstance() { return pool.obtain(); } //----------------------------------------------- // 序列化/反序列化对象,及类型信息 // 序列化的结果里,包含类型的信息 // 反序列化时不再需要提供类型 //----------------------------------------------- /** * 将对象【及类型】序列化为字节数组 * * @param obj 任意对象 * @param <T> 对象的类型 * @return 序列化后的字节数组 */ public static <T> byte[] writeToByteArray(T obj) { if (obj != null) { Kryo kryo = getInstance(); ByteArrayOutputStream os = null; Output output = null; try { os = new ByteArrayOutputStream(); output = new Output(os); kryo.writeClassAndObject(output, obj); output.flush(); close(output); return os.toByteArray(); } catch (Exception e) { log.error("writeToByteArray error", e); } finally { pool.free(kryo); close(os); } } return null; } /** * 关闭io流对象 * * @param closeable */ public static void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception e) { log.error("close error", e); } } } public static <T> T readFromByteArray(byte[] byteArray) { if (byteArray != null && byteArray.length > 0) { Kryo kryo = getInstance(); ByteArrayInputStream is = null; Output output = null; try { is = new ByteArrayInputStream(byteArray); Input input = new Input(is); return (T) kryo.readClassAndObject(input); } catch (Exception e) { log.error("readFromByteArray error", e); } finally { pool.free(kryo); close(is); close(output); } } return null; }}java.lang.RuntimeException: Buffer underflow: not enough data for compressed body at com.tplink.smb.component.cache.ohc.serializer.CompressdKryoSerializer.deserialize(CompressdKryoSerializer.java:63) at com.tplink.smb.component.cache.ohc.serializer.CompressdKryoSerializer.deserialize(CompressdKryoSerializer.java:21) at org.caffinitas.ohc.linked.OHCacheLinkedImpl.get(OHCacheLinkedImpl.java:198) at com.tplink.smb.component.cache.ohc.CacheServiceOhcImpl.get(CacheServiceOhcImpl.java:90) at com.tplink.smb.component.cache.ohc.CacheServiceOhcImplTest.getKeysByPattern(CacheServiceOhcImplTest.java:220) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)为什么读取compressedsize和originalsize的时候总是和实际不一致,而且差距巨大,导致后面检查数据时抛出运行时异常
最新发布
10-29
java.nio.BufferUnderflowException log.info("=== Tracker 小端数据解析 ==="); buffer.order(ByteOrder.LITTLE_ENDIAN); byte[] header = new byte[4]; buffer.get(header); byte cmd = buffer.get(); short length = buffer.getShort(); byte[] ts = new byte[6]; buffer.get(ts); long timestamp = 0; for (int i = ts.length - 1; i >= 0; i--) { timestamp = (timestamp << 8) | (ts[i] & 0xFF); } Date date = new Date(); date.setTime(timestamp); String uploadtime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date); mapinfo.put("upload_time", uploadtime); if (String.format("0x%02X", cmd).equals("0x02")) { short crc = buffer.getShort(); } if (String.format("0x%02X", cmd).equals("0x01")) { byte csq = buffer.get(); mapinfo.put("gps_signal", csq); byte gpsMaxSignal = buffer.get(); mapinfo.put("gps_max_signal", gpsMaxSignal); int longitude = buffer.getInt(); mapinfo.put("longitude", longitude / 1e6); int latitude = buffer.getInt(); mapinfo.put("latitude", latitude / 1e6); byte speed = buffer.get(); mapinfo.put("gps_speed", speed); short angle = buffer.getShort(); mapinfo.put("gps_cog", angle); byte[] iccid = new byte[20]; buffer.get(iccid); mapinfo.put("iccid", new String(iccid).trim()); byte[] imei = new byte[15]; buffer.get(imei); mapinfo.put("imei", new String(imei).trim()); int timestamp10 = buffer.getInt(); Date date2 = new Date(); date2.setTime((long) timestamp10 * 1000); // 秒 → 毫秒 String timestamp10Str = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date2); mapinfo.put("tracker_software_version", timestamp10Str); // 小区信息 JSONArray cellList = new JSONArray(); // 创建JSON数组 for (int i = 0; i < 10; i++) { int flag = buffer.getInt(); int cid = buffer.getInt(); int mcc = buffer.getInt(); int mnc = buffer.getInt(); int tac = buffer.getInt(); int pci = buffer.getInt(); int earfcn = buffer.getInt(); int rssi = buffer.getInt(); if (flag == 0 && cid == 0 && mcc == 0 && mnc == 0 && tac == 0 && pci == 0 && earfcn == 0 && rssi == 0) { break; } // 创建单个小区的JSON对象 JSONObject cell = new JSONObject(); cell.put("flag", flag); cell.put("cid", cid); cell.put("mcc", mcc); cell.put("mnc", mnc); cell.put("tac", tac); cell.put("pci", pci); cell.put("earfcn", earfcn); cell.put("rssi", rssi); cellList.add(cell); // 添加到JSON数组 } mapinfo.put("cell_info", cellList.toString()); short crc = buffer.getShort(); } 如何解决
09-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值