File: ByteBufferBackingArray.md

package info (click to toggle)
error-prone-java 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 23,204 kB
  • sloc: java: 222,992; xml: 1,319; sh: 25; makefile: 7
file content (80 lines) | stat: -rw-r--r-- 2,477 bytes parent folder | download
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();
   // ...
}
```