Serializable
Serializable — это свойство объекта или структуры данных, позволяющее преобразовывать его состояние в последовательный поток байтов (сериализовать) для последующего сохранения, передачи по сети или восстановления (десериализации). Термин широко используется в программировании, базах данных и распределённых системах. Объект, реализующий интерфейс или обладающий атрибутом, помечающим его как сериализуемый, называется сериализуемым.
История
Понятие сериализации возникло в ранних языках программирования, таких как Smalltalk (1970-е годы), где объекты могли быть сохранены в файл. В 1990-х годах с развитием распределённых вычислений и удалённого вызова процедур (RPC) сериализация стала ключевой технологией. В 1995 году в языке Java был введён интерфейс Serializable (пакет java.io), который позволял объектам автоматически сериализоваться в байтовый поток. В 2000-х годах с появлением веб-сервисов и XML/REST-API сериализация стала использоваться для обмена данными в форматах JSON, XML, YAML. В 2010-х годах с развитием микросервисной архитектуры и NoSQL-баз данных (например, MongoDB, Redis) сериализация стала неотъемлемой частью хранения и передачи данных.
Классификация
По способу реализации
- Встроенная сериализация — реализуется средствами языка программирования (например,
Serializableв Java,BinaryFormatterв .NET,pickleв Python). Требует минимальных усилий от разработчика, но может быть неэффективной или небезопасной. - Ручная сериализация — разработчик самостоятельно определяет, какие поля и как преобразовывать в байты (например, через методы
writeObject/readObjectв Java,__getstate__/__setstate__в Python). Позволяет оптимизировать производительность и контролировать безопасность. - Сериализация через библиотеки — использование сторонних библиотек (например,
Jacksonдля JSON в Java,protobufот Google,MessagePack). Обеспечивает кроссплатформенность, сжатие и скорость.
По формату данных
- Бинарная сериализация — данные преобразуются в компактный двоичный формат (например,
Java Serialization,Protocol Buffers,Avro,Thrift). Эффективна по размеру и скорости, но нечитаема человеком. - Текстовая сериализация — данные представляются в виде строк (например, JSON, XML, YAML, CSV). Читаема человеком, но занимает больше места и медленнее обрабатывается.
- Сериализация с кодировкой — комбинирует бинарную и текстовую формы (например,
Base64для встраивания бинарных данных в JSON).
По области применения
- Сериализация объектов — для сохранения состояния объектов в файл или передачи по сети (например, в Java RMI, .NET Remoting).
- Сериализация данных — для обмена данными между системами (например, JSON в REST API, XML в SOAP).
- Сериализация для кэширования — для быстрого восстановления состояния (например, в Redis, Memcached).
- Сериализация для распределённых вычислений — для передачи данных между узлами кластера (например, в Apache Spark, Hadoop).
Устройство и характеристики
Механизм работы
В большинстве языков программирования сериализация основана на рефлексии или метаданных. Для объекта, помеченного как сериализуемый, система анализирует его поля (включая приватные) и преобразует их в последовательность байтов. При десериализации создаётся новый экземпляр класса (без вызова конструктора) и заполняется данными из потока.
Ключевые характеристики
- Совместимость версий — возможность десериализовать данные, созданные старой версией класса, и наоборот. В Java для этого используется поле
serialVersionUID. - Производительность — скорость сериализации/десериализации и размер результирующих данных. Бинарные форматы обычно быстрее и компактнее текстовых.
- Безопасность — риск выполнения вредоносного кода при десериализации (например, атаки через
pickleв Python илиreadObjectв Java). Для защиты применяются белые списки классов, подписывание данных или использование безопасных форматов (JSON, Protocol Buffers). - Кроссплатформенность — возможность обмена данными между системами на разных языках (например, Java и Python через Protocol Buffers).
Примеры в языках программирования
- Java: интерфейс
java.io.Serializable(маркерный интерфейс). Класс должен реализовать его, а все поля (кромеtransientи статических) автоматически сериализуются. Пример:class Person implements Serializable { private String name; }. - Python: модуль
pickle. Любой объект, кроме системных (например, файловых дескрипторов), может быть сериализован. Пример:pickle.dumps(obj). - C#: атрибут
[Serializable](пространство имёнSystem). Поля по умолчанию сериализуются, кроме помеченных[NonSerialized]. Пример:[Serializable] public class Person { public string Name; }. - C++: нет встроенной сериализации; используются библиотеки (например,
Boost.Serialization,Cereal,protobuf). - JavaScript/TypeScript: сериализация через
JSON.stringify()иJSON.parse(), но только для простых типов (объекты, массивы, строки, числа). Для сложных объектов (с функциями, циклическими ссылками) требуются библиотеки (например,serialize-javascript).
Применение
Сохранение состояния
Сериализация используется для сохранения состояния приложения между сеансами работы (например, в играх, текстовых редакторах). Объекты (документы, настройки, игровые персонажи) сериализуются в файл и восстанавливаются при следующем запуске.
Передача данных по сети
В распределённых системах (веб-сервисы, микросервисы, RPC) сериализация преобразует объекты в байтовые потоки для отправки по HTTP, TCP/IP или другим протоколам. Например, в REST API объекты сериализуются в JSON, а в gRPC — в Protocol Buffers.
Кэширование
В системах кэширования (Redis, Memcached) объекты сериализуются для хранения в оперативной памяти. Это позволяет быстро восстанавливать часто используемые данные (например, результаты запросов к базе данных).
Распределённые вычисления
Фреймворки вроде Apache Spark и Hadoop сериализуют данные для передачи между узлами кластера. Например, в Spark объекты сериализуются с помощью Java Serialization или Kryo для эффективного распределения по исполнителям.
Базы данных
Некоторые базы данных (например, MongoDB, PostgreSQL) поддерживают сериализацию сложных типов (JSON, BSON) для хранения вложенных структур. В объектно-реляционных СУБД (например, Hibernate) объекты сериализуются для хранения в виде BLOB-полей.
Интересные факты
- В Java сериализация может быть неявной: если класс не реализует
Serializable, но содержит ссылку на сериализуемый объект, возникает исключениеNotSerializableException. - В Python модуль
pickleможет выполнять произвольный код при десериализации, что делает его небезопасным для данных из ненадёжных источников. Вместо него рекомендуется использоватьjsonилиshelve. - В C# атрибут
[Serializable]устарел в пользуSystem.Text.JsonиSystem.Runtime.Serialization.DataContractSerializerдля современных приложений. - Формат
Protocol Buffers(protobuf) от Google позволяет определять структуры данных в.proto-файлах и генерировать код для разных языков (Java, C++, Python, Go). Он обеспечивает высокую производительность и обратную совместимость. - В 2010-х годах сериализация стала мишенью для атак (например, уязвимость
CVE-2015-4852в Apache Commons Collections, позволявшая удалённое выполнение кода через Java-сериализацию). Это привело к разработке безопасных альтернатив (например,JSON,MessagePack).
Критика
- Безопасность — встроенная сериализация (особенно в Java и Python) часто содержит уязвимости, позволяющие выполнять произвольный код. Рекомендуется использовать только для доверенных данных или применять форматы без исполняемого кода (JSON, XML).
- Производительность — бинарная сериализация (например, Java Serialization) может быть медленной и создавать большие объёмы данных. Для высоконагруженных систем предпочтительны Protocol Buffers, Avro или Kryo.
- Совместимость версий — при изменении класса (добавление/удаление полей) старые сериализованные данные могут стать нечитаемыми. Требуется тщательное управление версиями (например,
serialVersionUIDв Java). - Сложность отладки — бинарные форматы нечитаемы человеком, что затрудняет анализ ошибок. Текстовые форматы (JSON, YAML) проще, но менее эффективны.
Источники
- Joshua Bloch. Effective Java (3rd edition). Addison-Wesley, 2018. — Глава «Сериализация».
- Python Software Foundation. pickle — Python object serialization. Документация Python 3.12.
- Microsoft. Serialization in .NET. Документация Microsoft.
- Google. Protocol Buffers. Документация protobuf.dev.
- Apache Spark. Tuning — Data Serialization. Документация Apache Spark.
- CVE-2015-4852 — Apache Commons Collections Remote Code Execution.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →