1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
`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:
* Ensure there is a backing array with `.hasArray()`
* Check the start position of the backing array by calling `.arrayOffset()`
* Check the end position of the backing array with `.remaining()`
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:
```java
// 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:
```java
// Use `.array()` only if you also check `.hasArray()`, `.arrayOffset()`, and `.remaining()`.
public void foo(ByteBuffer buffer) throws Exception {
if (buffer.hasArray()) {
int startIndex = buffer.arrayOffset();
int curIndex = buffer.arrayOffset() + buffer.position();
int endIndex = curIndex + buffer.remaining();
// Access elements of `.array()` with the above indices ...
}
}
```
or this:
```java
// 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:
```java
// 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:
```java
public void foo(ByteBuffer buffer) {
byte[] dataAsBytesArray = buffer.array();
// ...
}
```
|