java - 发送特定大小的数据时出现 BufferOverflowException

标签 java arrays buffer-overflow bytebuffer

我有一堆键和值,我想通过将它们打包在一个字节数组中来发送到我们的消息队列。我将创建一个包含所有键和值的字节数组,该数组应始终小于 50K,然后发送到我们的消息队列。我有标题,然后是数据。

数据包类别:

public final class Packet implements Closeable {
  private static final int MAX_SIZE = 50000;
  private static final int HEADER_SIZE = 36;

  private final byte dataCenter;
  private final byte recordVersion;
  private final long address;
  private final long addressFrom;
  private final long addressOrigin;
  private final byte recordsPartition;
  private final byte replicated;
  private final ByteBuffer itemBuffer = ByteBuffer.allocate(MAX_SIZE);
  private int pendingItems = 0;

  public Packet(final RecordPartition recordPartition) {
    this.recordsPartition = (byte) recordPartition.getPartition();
    this.dataCenter = Utils.LOCATION.getDatacenter();
    this.recordVersion = 1;
    this.replicated = 0;
    final long packedAddress = new Data().packAddress();
    this.address = packedAddress;
    this.addressFrom = 0L;
    this.addressOrigin = packedAddress;
  }

  private void addHeader(final ByteBuffer buffer, final int items) {
    buffer.put(dataCenter).put(recordVersion).putInt(items).putInt(buffer.capacity())
        .putLong(address).putLong(addressFrom).putLong(addressOrigin).put(recordsPartition)
        .put(replicated);
  }

  private void sendData() {
    if (itemBuffer.position() == 0) {
      // no data to be sent
      return;
    }
    final ByteBuffer buffer = ByteBuffer.allocate(MAX_SIZE);
    addHeader(buffer, pendingItems);
    // below line throws "BufferOverflowException"
    buffer.put(itemBuffer);
    SendRecord.getInstance().sendToQueueAsync(address, buffer.array());
    itemBuffer.clear();
    pendingItems = 0;
  }

  public void addAndSendJunked(final byte[] key, final byte[] data) {
    if (key.length > 255) {
      return;
    }
    final byte keyLength = (byte) key.length;
    final byte dataLength = (byte) data.length;

    final int additionalSize = dataLength + keyLength + 1 + 1 + 8 + 2;
    final int newSize = itemBuffer.position() + additionalSize;
    if (newSize >= (MAX_SIZE - HEADER_SIZE)) {
      sendData();
    }
    if (additionalSize > (MAX_SIZE - HEADER_SIZE)) {
      throw new AppConfigurationException("Size of single item exceeds maximum size");
    }

    final ByteBuffer dataBuffer = ByteBuffer.wrap(data);
    final long timestamp = dataLength > 10 ? dataBuffer.getLong(2) : System.currentTimeMillis();
    // data layout
    itemBuffer.put((byte) 0).put(keyLength).put(key).putLong(timestamp).putShort(dataLength)
        .put(data);
    pendingItems++;
  }

  @Override
  public void close() {
    if (pendingItems > 0) {
      sendData();
    }
  }
}

在上面的代码中,我在 sendData 方法中的 buffer.put(itemBuffer); 处收到 java.nio.BufferOverflowException 。我无法理解为什么会出现此异常以及如何修复它。

这是我调用此代码的方式:

Packet packet = new Packet(partition);
packet.addAndSendJunked("hello".getBytes(StandardCharsets.UTF_8), StringUtils.EMPTY.getBytes(StandardCharsets.UTF_8));
packet.close();

最佳答案

显然 itemBuffer 加上已放入 buffer 中的 header 长度超过了 buffer.capacity(),即 MAX_SIZE。

因此要么 addHeader() 或创建 itemBuffer 的任何内容存在错误,或者 MAX_SIZE 太小。

注意

SendRecord.getInstance().sendToQueueAsync(address, buffer.array());

在这里,您将 MAX_SIZE 字节的整个缓冲区排入队列,即使您可能没有将 MAX_SIZE 字节放入其中。最好将 buffer 本身传递给此方法,并避免代码中不断的换行。

关于java - 发送特定大小的数据时出现 BufferOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49269250/

相关文章:

python - 使用 bool 数组在 DataFrame(或 ndarray)中有效设置一维范围值

c - 简单的缓冲区溢出漏洞利用

c - 返回 libc 攻击

java - 用于验证媒体播放器的android单元测试

c++ - 检查 C++ 数组是否为 Null

arrays - 不同类型的 RxSwift 变量数组

c - 如何在 C 中正确实现健壮的堆栈

java - 以 ArrayList 作为参数相乘列表元素的方法

java - 为什么需要从 Integer 转换为 int

java - 使用变量类名而不是大量的 if 子句?