В других ответах есть много хороших моментов, но одной вещи не хватает в том, что механизм сериализации может кэшировать определенные объекты .
Например, вы сериализуете серию объектов A, B и C одного и того же класса, которые содержат два объекта o1 и o2 в каждом объекте. Допустим, что объем служебных данных составляет 100 байт, и скажем, что объекты выглядят следующим образом:
Object shared = new Object();
Object shread2 = new Object();
A.o1 = new Object()
A.o2 = shared
B.o1 = shared2
B.o2 = shared
C.o1 = shared2
C.o2 = shared
Для простоты мы можем сказать, что универсальные объекты занимают 50 байтов для сериализации, а размер сериализации A составляет 100 (служебные данные) + 50 (o1) + 50 (o2) = 200 байтов. Можно также сделать аналогичную наивную оценку для B и C. Однако, если все три сериализуются одним и тем же выходным потоком объекта до того, как будет вызван сброс, вы увидите в потоке сериализацию A и o1 и o2, затем сериализация B и o1 для b, НО ссылка на o2, поскольку это был тот же объект, который уже был сериализован . Допустим, ссылка на объект занимает 16 байт, размер B теперь равен 100 (накладные расходы) + 50 (o1) + 16 (ссылка на o2) = 166. Так что размер, необходимый для сериализации, теперь изменился!
Мы могли бы выполнить вычисление simialr для C и получить 132 байта с кэшированием двух объектов, поэтому размер сериализации для всех трех объектов будет разным с разницей в ~ 33% между самым большим и самым маленьким.
Таким образом, если вы не сериализуете весь объект без кэша каждый раз, трудно точно оценить размер, необходимый для сериализации объекта.