2015-05-29 7 views
5

Предположим, что у меня есть метод void foo(byte[] bytes), поэтому в качестве его параметра требуется массив байтов. Howerver, тип Java для байтовых массивов в Protobuf - ByteString.Буферы протоколов: получить массив байтов из ByteString без копирования

Я могу использовать byte[] toByteArray(), чтобы получить массив байтов. Но проблема заключается в том, что этот метод создает новый массив с использованием копии, что относительно дорого. Я бы предпочел, чтобы он возвращал базовый массив напрямую или вместо этого возвращал представление.

Есть ли какой-либо API для этого, или штраф за исполнение допустим?

+0

Что делает метод foo (byte [] bytes)? Можете ли вы изменить его реализацию? – kostya

+0

@kostya Вы имеете в виду, что я могу использовать 'ByteString # writeTo (OutputStream)' вместо этого? Но я действительно хочу, чтобы мои модули были отделены друг от друга. – duleshi

+0

Да, что-то вроде 'writeTo'. 'OutputStream' - это класс из стандартной библиотеки, поэтому вы все равно можете сохранить foo() метод protobuf бесплатно. Javadocs для 'ByteString' четко заявляют, что то, что вы просите, невозможно: как и' String', содержимое «ByteString» никогда не может измениться, даже при наличии гонки данных или неправильного использования API в клиентском коде , – kostya

ответ

4

В общем, это невозможно, поскольку в некоторых подклассах ByteString такого массива не может быть. BoundedByteString может содержать больший массив, поэтому для получения массива нужного размера требуется копирование. RopeByteString состоит из других байтовых строк, поэтому копирование требуется для помещения содержимого в один массив. LiteralByteString хранит его содержимое в массиве нужного размера, но не предоставляет методы для непосредственного доступа к нему.

Но, скорее всего, toByteArray() будет достаточно быстро для ваших нужд, так как System.arraycopy() очень быстр.

Если у вас действительно есть проблемы с производительностью из-за длинных массивов копирования и вы не хотите, чтобы пройти ByteString прямо, посмотрите на asReadOnlyByteBuffer() и asReadOnlyByteBufferList() методов. Они обертывают содержимое ByteString в ByteBuffer без их копирования.

2

Вы не можете получить byte[] от ByteString без копирования, так как это позволит вам изменять содержимое ByteString, что означает, что ByteString больше не может гарантировать, что она неизменна. Это очень похоже на то, почему вы не можете получить char[] от String без копирования, хотя String действительно поддерживается char[] под капотом. Это может быть проблемой безопасности: при передаче String или ByteString между доменами безопасности важно, чтобы получатель мог знать, что отправитель не изменяет строку из-под них, пока они ее используют.

Вы можете, однако, позвонить asReadOnlyByteBufferList(), чтобы получить ByteBuffer s, представляющий базовые данные без копии, так как ByteBuffer обеспечивает неизменность.

Смежные вопросы