У меня есть клиент и сервер, обменивающиеся данными через удаленное взаимодействие Spring (с использованием сериализации Java) через проприетарную систему обмена сообщениями. Мой сервер возвращает большие объекты, поэтому моя реализация удаленного взаимодействия Spring разбивает сериализованный байтовый массив объектов на блоки и отправляет несколько сообщений. Клиент ожидает все ответные сообщения для данного запроса и в конечном итоге вызывает метод ниже для десериализации массивов байтов в результирующий объект.
protected Object deserialize(List<byte[]> blocks) {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream(blocks.size() * blockSize);
for (byte[] b : blocks) {
os.write(b, 0, b.length);
}
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
ObjectInputStream objInputStream = new ObjectInputStream(is);
return objInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Это работает отлично. Однако память очень тяжелая. Предполагая, что объект в памяти имеет примерно такой же размер, как его сериализованный байтовый массив в памяти, я получаю в 3 раза больше размера моего объекта в памяти:
-
List<byte[]>
, содержащий блоки
-
ByteArrayOutputStream
, содержащий каскадный байтовый массив (и, возможно, другой, потому что ByteArrayOutputStream.toByteArray()
копирует массив).
- Полученный Объект
Как только этот метод возвращает все массивы могут быть GC'd, но во время этого вызова метода есть большой всплеск использования памяти.
Итак, на мой вопрос: есть ли способ, которым я могу создать входной поток блокирующих байтов, к которому я могу добавлять байтовые массивы, когда я их получаю? ObjectOutputStream (в отдельном потоке) считывает доступные байты, затем блокирует их до тех пор, пока не будет записано больше байтов, и продолжит работу до полной десериализации объекта. Таким образом, мне никогда не нужно иметь полный конкатенированный байтовый массив в памяти. Кажется, что ни одна из стандартных реализаций потока не подходит, я не понимаю, как бы я использовал NIO для этого, и я бы не стал писать свою собственную реализацию потока, если бы там было достаточно.
Большое спасибо,
Ian