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

В последнее время я пытаюсь узнать больше и вообще тестировать сериализацию 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?

Ответы

Ответ 1

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

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

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

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

  • XML и JSON, как вы показали (различные XML-вкусы, конечно)
  • YAML
  • Facebook Thrift (RPC, а также сериализация)
  • Буферы протокола Google
  • Hessian (веб-службы, а также сериализация)
  • Apache Avro
  • Ваш собственный пользовательский формат

(Отказ от ответственности: я работаю в Google, и я делаю порт протокольных буферов на С# в качестве моего 20% -ного проекта, поэтому я считаю, что хорошая технология:)

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

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

Всякий раз, когда мы хотим сериализовать объект, мы реализуем интерфейс java.io.Serializable. Интерфейс, который не имеет каких-либо методов для реализации, несмотря на то, что мы его реализуем, указывает на компилятор или JVM (известный как Маркерный интерфейс). Поэтому, если 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 с помощью фреймворков.