ByteBufferBackingArray
ByteBuffer.array() shouldn't be called unless ByteBuffer.arrayOffset() is used or if the ByteBuffer was initialized using ByteBuffer.wrap() or ByteBuffer.allocate().

Severity
WARNING
Has Fix?
NO_FIX

The problem

ByteBuffer provides a view of an underlying bytes storage. The two most common implementations are the non-direct byte buffers, which are backed by a bytes array, and direct byte buffers, which usually are off-heap directly mapped to memory. Thus, not all ByteBuffer implementations are backed by a bytes array, and when they are, the beginning of the array returned by .array() may not necessarily correspond to the beginning of the ByteBuffer.

Since it’s so finicky, use of .array() is discouraged. Use .get(...) to copy the underlying data instead.

But, if you absolutely must use .array() to look behind the ByteBuffer curtain, check all of the following:

If you know that the ByteBuffer was created locally with ByteBuffer.wrap(...) or ByteBuffer.allocate(...), it’s safe, you can use the backing array normally, without checking the above.

Do this:

// Use `.get(...)` to copy the byte[] without changing the current position.
public void foo(ByteBuffer buffer) throws Exception {
   byte[] bytes = new byte[buffer.remaining()];
   buffer.get(bytes);
   buffer.position(buffer.position() - bytes.length); // Restores the buffer position
   // ...
}

or this:

// Use `.array()` only if you also check `.hasArray()`, `.arrayOffset()`, and `.remaining()`.
public void foo(ByteBuffer buffer) throws Exception {
  if (buffer.hasArray()) {
    int startIndex = byteBuffer.arrayOffset();
    int curIndex = byteBuffer.arrayOffset() + byteBuffer.position();
    int endIndex = curIndex + byteBuffer.remaining();
    // Access elements of `.array()` with the above indices ...
  }
}

or this:

// No checking necessary when the buffer was constructed locally with `allocate(...)`.
public void foo() throws Exception {
      ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
      buffer.putLong(1L);
      // ...
      buffer.array();
      // ...
}

or this:

// No checking necessary when the buffer was constructed locally with `wrap(...)`.
public void foo(byte[] bytes) throws Exception {
   ByteBuffer buffer = ByteBuffer.wrap(bytes);
   // ...
   buffer.array();
   // ...
}

Not this:

public void foo(ByteBuffer buffer) {
   byte[] dataAsBytesArray = buffer.array();
   // ...
}

Suppression

Suppress false positives by adding the suppression annotation @SuppressWarnings("ByteBufferBackingArray") to the enclosing element.