Журнал Python, конечно! BTW они ищут участников...
Чтобы асинхронный ввод-вывод работал, у вас должна быть непрерывная память. В C вы можете попытаться перераспределить массив, но в Java вы должны выделить новую память. Вы можете записать в ByteArrayOutputStream
, а затем преобразовать его в ByteBuffer
, когда будете готовы его отправить. Обратной стороной является то, что вы копируете память, и один из ключей к эффективному вводу-выводу - уменьшение количества копий памяти.
Взгляните на Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html , который является drop in replace (он обертывает ByteBuffer)
Однако я предлагаю вам выделить больше, чем вам нужно, и не беспокоиться об этом слишком сильно. Если вы выделяете буфер (особенно прямой буфер), ОС предоставляет ему виртуальную память, но она использует физическую память только тогда, когда она фактически используется. Виртуальная память должна быть очень дешевой.
ByteBuffer не может работать таким образом, поскольку его концепция дизайна должна быть просто представлением определенного массива, на который вы также можете иметь прямую ссылку. Он не может попытаться заменить этот массив на более крупный массив без каких-либо странностей.
Вы хотите использовать DataOutput
. Наиболее удобный способ - использовать (предварительную) библиотеку Guava:
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.write(someBytes);
out.writeInt(someInt);
// ...
return out.toByteArray();
Но вы также можете создать DataOutputStream из ByteArrayOutputStream вручную и просто обработать ложные исключения IOExceptions, связав их в AssertionErrors.
Другой вариант - использовать прямую память с большим буфером. Это потребляет виртуальную память, но использует только столько физической памяти, сколько вы используете (на страницу, которая обычно составляет 4K)
Таким образом, если вы выделяете буфер размером 1 MB, он потребляет 1 MB виртуальной памяти, но ОС отдает приложению только физические страницы, которые оно фактически использует.
В результате вы видите, что ваше приложение использует много виртуальной памяти, но относительно небольшое количество резидентной памяти.
Возможно, стоит также взглянуть на Netty's DynamicChannelBuffer . Мне пригодились следующие вещи:
slice (int index, int length)