Java Reference
In-Depth Information
ByteBuffer
provides support for dealing directly with the native capabilities of the
platform the JVM is running on.
This approach is called the “direct buffers” case, and it bypasses the Java heap wher‐
ever possible. Direct buffers are allocated in native memory, not on the standard
Java heap, and they are not subject to garbage collection in the same way as regular
on-heap Java objects.
g
d
O
e
To obtain a direct
ByteBuffer
, call the
allocateDirect()
factory method. An on-
heap version,
allocate()
, is also provided, but in practice this is not often used.
A third way to obtain a byte buffer is to wrap an existing
byte[]
—this will give an
on-heap buffer that serves to provide a more object-oriented view of the underlying
bytes:
ByteBuffer
b
=
ByteBuffer
.
allocateDirect
(
65536
);
ByteBuffer
b2
=
ByteBuffer
.
allocate
(
4096
);
byte
[]
data
=
{
1
,
2
,
3
};
ByteBuffer
b3
=
ByteBuffer
.
wrap
(
data
);
Byte buffers are all about low-level access to the bytes. This means that developers
have to deal with the details manually—including the need to handle the endianness
of the bytes and the signed nature of Java's integral primitives:
b
.
order
(
ByteOrder
.
BIG_ENDIAN
);
int
capacity
=
b
.
capacity
();
int
position
=
b
.
position
();
int
limit
=
b
.
limit
();
int
remaining
=
b
.
remaining
();
boolean
more
=
b
.
hasRemaining
();
To get data in or out of a buffer, we have two types of operation—single value,
which reads or writes a single value, and bulk, which takes a
byte[]
or
ByteBuffer
and operates on a (potentially large) number of values as a single operation. It is
from the bulk operations that performance gains would expect to be realized:
b
.
put
((
byte
)
42
);
b
.
putChar
(
'x'
);
b
.
putInt
(
0xcafebabe
);
b
.
put
(
data
);
b
.
put
(
b2
);
double
d
=
b
.
getDouble
();
b
.
get
(
data
,
0
,
data
.
length
);
The single value form also supports a form used for absolute positioning within the
buffer:
b
.
put
(
0
,
(
byte
)
9
);