Знаете, почему после записи ByteBuffer данные сразу не читаются?
У буфера есть position и limit. После put позиция указывает на место следующей записи, поэтому сначала переключаем его из режима записи в режим чтения:
buffer.put(payload);
buffer.flip();
flip переносит текущую position в limit и возвращает position в начало. Теперь чтение ограничено только записанными байтами, а не всей ёмкостью буфера.
Читаем данные, пока между position и limit остаются байты:
while (buffer.hasRemaining()) {
process(buffer.get());
}
После чтения clear подготавливает буфер к новой записи. Он сбрасывает position и limit, но не стирает старые байты, поэтому счётчики состояния нельзя путать с очисткой памяти.
Если часть данных ещё не обработана, compact сохраняет остаток в начале и оставляет место для новых байтов:
buffer.compact();
buffer.put(nextChunk);
Такой цикл удобен при чтении неполных сетевых сообщений. Остаток переносится вперёд, а новые данные дописываются после него.