Как работает сериализация в Java и когда ее следует использовать вместо какого-либо другого метода сохранения? - PullRequest
39 голосов
/ 09 декабря 2008

В последнее время я пытался узнать больше и вообще тестировать сериализацию Java как для рабочих, так и для личных проектов, и я должен сказать, что чем больше я знаю об этом, тем меньше мне это нравится. Это может быть вызвано дезинформацией, поэтому я спрашиваю у вас две вещи:

1: На уровне байтов, как сериализация знает, как сопоставить сериализованные значения с некоторым классом?

Одна из моих проблем заключается в том, что я провел небольшой тест с ArrayList, содержащий значения «один», «два», «три». После сериализации байтовый массив занял 78 байтов, что кажется очень большим для такого небольшого количества информации (19 + 3 + 3 + 4 байта). Конечно, есть некоторые накладные расходы, но это приводит ко второму вопросу:

2: Можно ли считать сериализацию хорошим методом для сохранения объектов вообще? Теперь, очевидно, если бы я использовал какой-нибудь самодельный формат XML, данные о сохранении были бы примерно такими:

<object>
    <class="java.util.ArrayList">
    <!-- Object array inside Arraylist is called elementData -->
    <field name="elementData">
        <value>One</value>
        <value>Two</value>
        <value>Three</value>
    </field>
</object>

, который, как и XML в целом, немного раздут и занимает 138 байт (то есть без пробелов). То же самое в JSON может быть

{
    "java.util.ArrayList": {
        "elementData": [
            "one",
            "two",
            "three"
        ]
    }
}

, что на 75 байт уже немного меньше, чем в сериализации Java. С этими текстовыми форматами, конечно же, очевидно, что должен быть способ представить ваши основные данные в виде текста, чисел или любой их комбинации.

Итак, резюмируем, как сериализация работает на уровне байтов / бит, когда она должна использоваться и когда ее не следует использовать, и каковы реальные преимущества сериализации, кроме того, что она является стандартной в Java?

Ответы [ 9 ]

47 голосов
/ 09 декабря 2008

Я бы лично попытался избежать "встроенной" сериализации Java:

  • Это не переносимо на другие платформы
  • Это не очень эффективно
  • Это хрупко - заставить его справиться с несколькими версиями класса довольно сложно. Даже смена компиляторов может нарушить сериализацию, если вы не будете осторожны.

Подробнее о том, что означают настоящие байты, см. Спецификация сериализации Java-объекта .

Существуют различные альтернативы, такие как:

(Отказ от ответственности: я работаю на Google, и я делаю порт Protocol Buffers на C # как мой 20% проект, так что я думаю, что это хорошая технология:)

Кроссплатформенные форматы почти всегда более ограничительны, чем форматы для конкретных платформ, по очевидным причинам - например, у Protocol Buffers довольно ограниченный набор нативных типов - но совместимость может быть невероятно полезной. Вам также необходимо учитывать влияние контроля версий с обратной и прямой совместимостью и т. Д. Текстовые форматы обычно редактируются вручную, но, как правило, менее эффективны как в пространстве, так и во времени.

По сути, вам нужно внимательно изучить ваши требования.

8 голосов
/ 09 декабря 2008

Основным преимуществом сериализации является то, что она чрезвычайно проста в использовании, относительно быстра и сохраняет фактические сетки объектов Java.

Но вы должны понимать, что на самом деле он предназначен не для хранения данных, а главным образом для обмена данными между различными экземплярами JVM по сети с использованием протокола RMI.

5 голосов
/ 09 декабря 2008

см. Java Object Протокол потока сериализации для описания формата файла грамматики, используемой для сериализованных объектов.

Лично я считаю, что встроенная сериализация приемлема для сохранения недолговечных данных (например, хранения состояния объекта сеанса между http-запросами), что не относится к вашему приложению.

Для данных, которые имеют более длительное время жизни или должны использоваться вне вашего приложения, я бы сохранил их либо в базе данных, либо, по крайней мере, в более широко используемом формате ...

4 голосов
/ 06 января 2016

Как работает встроенная сериализация в Java?

Всякий раз, когда мы хотим сериализовать объект, мы реализуем интерфейс java.io.Serializable. Интерфейс, который не имеет методов для реализации, даже если мы реализуем его для , указывает что-то компилятору или JVM (известный как Marker Interface ) Поэтому, если JVM видит, что класс Serializable, он выполняет некоторую операцию предварительной обработки этих классов. Операция заключается в добавлении следующих двух примеров методов.

private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.writeObject(name); // object property
        stream.writeObject(address); // object property
    }

    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        name = (String) stream.readObject(); // object property
        address = (String) stream.readObject();// object property
    }

Когда его следует использовать вместо какой-либо другой техники настойчивости?

Встроенный Serialization полезен, когда отправитель и получатель оба являются Java. Если вы хотите избежать вышеуказанных проблем, мы используем XML или JSON с помощью фреймворков.

0 голосов
/ 15 мая 2009

Если у вас не слишком много данных, вы можете сохранить объекты в объект java.util.Properties. Примером пары ключ / значение может быть user_1234_firstname = Peter. Использование отражения для сохранения и загрузки объектов может упростить задачу.

0 голосов
/ 14 декабря 2008

Причина, по которой хранение небольшого количества информации является последовательной формой, относительно велика, потому что она хранит информацию о классах объектов, которые сериализует. Если вы сохраните дубликат вашего списка, то увидите, что файл сильно не вырос. Храните один и тот же объект дважды, и разница будет крошечной.

Важные плюсы: относительно прост в использовании, довольно быстр и может развиваться (как XML). Тем не менее, данные довольно непрозрачны, они только для Java, тесно связывают данные с классами, и ненадежные данные могут легко вызвать DoS. Вы должны думать о сериализованной форме, а не просто шлепать implements Serializable везде.

0 голосов
/ 09 декабря 2008

Преимущество Java Object Serialization (JOS) в том, что он просто работает. Есть также инструменты, которые делают то же самое, что и JOS, но используют формат XML вместо двоичного формата.

О длине: JOS записывает некоторую информацию о классе в начале, а не как часть каждого экземпляра - например, полные имена полей записываются один раз, а индекс в этом списке имен используется для экземпляров класса. Это удлиняет вывод, если вы пишете только один экземпляр класса, но более эффективно, если вы пишете несколько (разных) его экземпляров. Мне не ясно, использует ли ваш пример класс, но это основная причина, почему JOS длиннее, чем можно было ожидать.

Кстати: это случайно, но я не думаю, что JSON записывает имена классов (как у вас в вашем примере), и поэтому он может не делать то, что вам нужно.

0 голосов
/ 09 декабря 2008

Сериализация означает, что вы помещаете свои структурированные данные в классы в единый порядок байт-кода для его сохранения.

Обычно вы должны использовать другие методы, кроме jav-метода buildin, он просто создан для работы «из коробки», но если в ваших сериализованных классах в будущем будут какие-то изменения содержимого или изменения порядка, у вас возникнут проблемы, поскольку Я не могу загрузить их правильно.

0 голосов
/ 09 декабря 2008

Я столкнулся с этой дилеммой около месяца назад (см. вопрос, который я задал ).

Основной урок, который я извлек из этого, заключается в использовании сериализации Java только тогда, когда это необходимо, и если нет другого выбора. Как сказал Джон, у него есть свои недостатки, в то время как другие методы сериализации намного проще, быстрее и более переносимы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...