В чем разница между сериализацией и маршалингом?


522

Я знаю, что в терминах нескольких распределенных методов (таких как RPC) используется термин «маршалинг», но я не понимаю, чем он отличается от сериализации. Разве они не превращают объекты в серию битов?

Связанные с:

Что такое сериализация?

Что такое Маршаллинг объектов?

Ответы:


405

Маршалинг и сериализация слабо синонимичны в контексте удаленного вызова процедуры, но семантически различаются с точки зрения намерения.

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

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

Как упоминает @Bill, могут быть дополнительные метаданные, такие как расположение базы кода или даже код реализации объекта.


3
Есть ли слово, которое означает сериализацию и десериализацию одновременно? Нужно имя для интерфейса с этими методами.
Раффиан

1
@raffian, вы имеете в виду интерфейс, реализуемый объектом, который подвергается сериализации и десериализации, или объектом, ответственным за управление процессом? Ключевыми словами, которые я бы предложил, являются «Serializable» и «Formatter» соответственно; украшать лидирующими I, капитализированными изменениями и т. д. по мере необходимости.
Джеффри Хантин

@JeffreyHantin Я имею в виду объект, отвечающий за управление процессом; Я сейчас использую ISerializer, но это только наполовину верно :)
raffian

6
@raffian в области телекоммуникаций, мы называем компонент, который сериализует и десериализует «SerDes» или «serdes», обычно произносится как sir-dez или sir-deez в зависимости от предпочтения. Я предполагаю, что это похоже на «модем» (то есть «модулятор-демодулятор») по своей конструкции.
Давида

2
@naki, это общеотраслевой - если вы посмотрите на таблицы высокоскоростных ПЛИС, они упомянут функциональность SERDES, хотя все они довольно современны, начиная с 1990-х годов. Google NGrams предполагает, что он стал более популярным в 1980-х годах, хотя я нашел экземпляр в
таблице данных

208

Оба делают одно общее - это сериализация объекта. Сериализация используется для передачи объектов или их хранения. Но:

  • Сериализация: при сериализации объекта в поток байтов записываются только данные члена этого объекта; не код, который фактически реализует объект.
  • Marshalling: термин Marshalling используется, когда мы говорим о передаче объекта удаленным объектам (RMI) . В Marshalling Object сериализуется (данные члена сериализуются) + Codebase прикреплен.

Так что сериализация является частью Marshalling.

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


45
+1 за определение того, что CodeBase означает в этом контексте
Омар Салем

2
Маршалинг без сериализации происходит. См. Swing invokeAndWaitи Forms Invoke, в которых выполняется синхронный вызов потока пользовательского интерфейса без использования сериализации.
Джеффри Хантин

2
«не код, который фактически реализует объект»: означает ли это методы класса? или что это значит. Можете ли вы объяснить, пожалуйста.
Вишал Ананд

2
Что ты имеешь ввиду the implementation of this object? Не могли бы вы привести конкретный пример Serializationи Marshalling?
Симин Цзе

Выделение без сериализации происходит в некоторых контекстах, например, когда вызов функции передает поток управления между моделями потоков (например, между общим пулом потоков и библиотекой с одним закрепленным потоком) в рамках одного процесса. Вот почему я говорю, что они слабо синонимичны в контексте RPC .
Джеффри Хантин

94

Из статьи Marshalling (информатика) из Википедии:

Термин «маршал» считается синонимом «сериализации» в стандартной библиотеке Python 1 , но термины не являются синонимами в RFC 2713, связанном с Java:

«Маршалировать» объект означает записывать его состояние и кодовую базу (ы) таким образом, чтобы, когда маршаллированный объект был «не маршалированным», была получена копия исходного объекта, возможно, путем автоматической загрузки определений классов объекта. Вы можете маршалировать любой объект, который можно сериализовать или удалить. Маршаллинг подобен сериализации, за исключением того, что маршаллинг также записывает кодовые базы. Маршаллинг отличается от сериализации тем, что маршаллинг специально обрабатывает удаленные объекты. (RFC 2713)

«Сериализация» объекта означает преобразование его состояния в поток байтов таким образом, что поток байтов может быть преобразован обратно в копию объекта.

Таким образом, сортировка также сохраняет кодовую базу объекта в потоке байтов в дополнение к его состоянию.


1
Вы имеете в виду, что объект, если он не сериализован, может просто иметь состояние, не будет никакой кодовой базы, то есть ни одна из его функций не может быть вызвана, это просто структурированный тип данных. И, если тот же объект маршаллируется, то он будет иметь свою кодовую базу вместе со структурой и однажды сможет вызывать свои функции?
Бьян

11
«Кодовая база» на самом деле не означает «Код». Из "Как работает Codebase" ( goo.gl/VOM2Ym ) Codebase довольно просто показывает, как программы, использующие семантику RMI для удаленной загрузки классов, находят новые классы. Когда отправитель объекта сериализует этот объект для передачи в другую JVM, он аннотирует сериализованный поток байтов информацией, называемой кодовой базой. Эта информация сообщает получателю, где можно найти реализацию этого объекта. Фактическая информация, хранящаяся в аннотации кодовой базы, представляет собой список URL-адресов, с которых можно загрузить файл класса для нужного объекта.
Джузеппе Бертоне

2
@Neurone Это определение относится к Jini и RMI. «Codebase» - это общий термин. ru.wikipedia.org/wiki/Codebase
Билл Ящерица

2
@BilltheLizard Да, но поскольку вы говорите о маршаллинге в Java, неправильно говорить, что разница между сериализацией и маршаллингом заключается в том, что «маршаллинг сохраняет код объекта в дополнение к его состоянию», и это приводит к вопросу бьян. Маршаллинг сохраняет «кодовую базу» в дополнение к состоянию объекта.
Джузеппе Бертоне

19

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

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

При этом, как правило, они являются синонимами.


2
Вы имеете в виду, что объект, если он не сериализован, может просто иметь состояние, не будет никакой кодовой базы, то есть ни одна из его функций не может быть вызвана, это просто структурированный тип данных. И, если тот же объект маршалируется, то у него будет своя кодовая база вместе со структурой, и можно будет вызывать его функции?
Бьян

18

Маршалинг относится к преобразованию сигнатуры и параметров функции в один байтовый массив. Специально для целей RPC.

Сериализация чаще всего относится к преобразованию всего дерева объектов / объектов в байтовый массив. Marshaling будет сериализовать параметры объекта, чтобы добавить их в сообщение и передать его по сети. * Сериализация также может быть использована для хранения на диск. *


11

Marshalling - это правило, сообщающее компилятору, как данные будут представлены в другой среде / системе; Например;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;

как вы можете видеть два разных строковых значения, представленные в виде разных типов значений.

Сериализация будет преобразовывать только содержимое объекта, а не представление (останется прежним) и подчиняться правилам сериализации (что экспортировать или нет). Например, частные значения не будут сериализованы, публичные значения yes и структура объекта останутся прежними.


7

Вот более конкретные примеры обоих:

Пример сериализации:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    char value[11];
} SerializedInt32;

SerializedInt32 SerializeInt32(int32_t x) 
{
    SerializedInt32 result;

    itoa(x, result.value, 10);

    return result;
}

int32_t DeserializeInt32(SerializedInt32 x) 
{
    int32_t result;

    result = atoi(x.value);

    return result;
}

int main(int argc, char **argv)
{    
    int x;   
    SerializedInt32 data;
    int32_t result;

    x = -268435455;

    data = SerializeInt32(x);
    result = DeserializeInt32(data);

    printf("x = %s.\n", data.value);

    return result;
}

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

Marshalling Demo:

(MarshalDemoLib.cpp)

#include <iostream>
#include <string>

extern "C"
__declspec(dllexport)
void *StdCoutStdString(void *s)
{
    std::string *str = (std::string *)s;
    std::cout << *str;
}

extern "C"
__declspec(dllexport)
void *MarshalCStringToStdString(char *s)
{
    std::string *str(new std::string(s));

    std::cout << "string was successfully constructed.\n";

    return str;
}

extern "C"
__declspec(dllexport)
void DestroyStdString(void *s)
{
    std::string *str((std::string *)s);
    delete str;

    std::cout << "string was successfully destroyed.\n";
}

(MarshalDemo.c)

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char **argv)
{
    void *myStdString;

    LoadLibrary("MarshalDemoLib");

    myStdString = ((void *(*)(char *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "MarshalCStringToStdString"
    ))("Hello, World!\n");

    ((void (*)(void *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "StdCoutStdString"
    ))(myStdString);

    ((void (*)(void *))GetProcAddress (
        GetModuleHandleA("MarshalDemoLib"),
        "DestroyStdString"
    ))(myStdString);    
}

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

Маршалинг не требует участия в динамическом распределении, он также может быть просто трансформацией между структурами. Например, у вас может быть пара, но функция ожидает, что первый и второй элементы пары будут другими; если вы разыгрываете / memcpy одну пару на другую, вы не будете выполнять эту работу, потому что fst и snd перевернутся.

#include <stdio.h>

typedef struct {
    int fst;
    int snd;
} pair1;

typedef struct {
    int snd;
    int fst;
} pair2;

void pair2_dump(pair2 p)
{
    printf("%d %d\n", p.fst, p.snd);
}

pair2 marshal_pair1_to_pair2(pair1 p)
{
    pair2 result;
    result.fst = p.fst;
    result.snd = p.snd;
    return result;
}

pair1 given = {3, 7};

int main(int argc, char **argv)
{    
    pair2_dump(marshal_pair1_to_pair2(given));

    return 0;
}

Концепция маршалинга становится особенно важной, когда вы начинаете иметь дело с помеченными объединениями многих типов. Например, вам может быть сложно заставить движок JavaScript печатать для вас «c-строку», но вы можете попросить его вывести для вас упакованную c-строку. Или, если вы хотите напечатать строку из среды выполнения JavaScript в среде исполнения Lua или Python. Они все струны, но часто не обходятся без маршалинга.

Недовольство, которое я недавно испытывал, заключалось в том, что JScript массив маршалирует в C # как «__ComObject» и не имеет документированного способа играть с этим объектом. Я могу найти адрес, где он находится, но я действительно ничего больше не знаю об этом, поэтому единственный способ действительно выяснить это - ткнуть в нее любым возможным способом и, надеюсь, найти полезную информацию об этом. Таким образом, становится проще создать новый объект с более дружественным интерфейсом, таким как Scripting.Dictionary, скопировать в него данные из объекта массива JScript и передать этот объект в C # вместо массива JScript по умолчанию.

test.js:

var x = new ActiveXObject("Dmitry.YetAnotherTestObject.YetAnotherTestObject");

x.send([1, 2, 3, 4]);

YetAnotherTestObject.cs

using System;
using System.Runtime.InteropServices;

namespace Dmitry.YetAnotherTestObject
{
    [Guid("C612BD9B-74E0-4176-AAB8-C53EB24C2B29"), ComVisible(true)]
    public class YetAnotherTestObject
    {
        public void send(object x)
        {
            System.Console.WriteLine(x.GetType().Name);
        }
    }
}

выше печатает "__ComObject", который является чем-то вроде черного ящика с точки зрения C #.

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


4

Маршаллинг обычно находится между относительно тесно связанными процессами; Сериализация не обязательно имеет такое ожидание. Так, например, при распределении данных между процессами вы можете просто послать ССЫЛКУ на потенциально дорогостоящие данные для восстановления, тогда как при сериализации вы хотели бы сохранить все это, чтобы правильно воссоздать объект (ы) после десериализации.


4

Мое понимание сортировки отличается от других ответов.

Сериализация:

Создание или регидратация версии графов объектов в проводном формате с использованием соглашения.

сортировочных:

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

Первая контрактная разработка:

Маршаллинг важен в контексте первой разработки контракта.

  • Можно вносить изменения во внутренний граф объектов, сохраняя стабильность внешнего интерфейса с течением времени. Таким образом, всем абонентам службы не нужно будет изменять каждое тривиальное изменение.
  • Можно отобразить результаты на разных языках. Например, от соглашения имени свойства одного языка ('имя_свойства') к другому ('имя_свойства').

1
// Могу ли я узнать больше о том, что конкретно означает «регидрат», в этом ответе здесь @JasperBlues? Я предполагаю, что это не только для еды Астронавта.
Натан Басанезе

@NathanBasanese согласно этому ответу - stackoverflow.com/a/6991192/5101816 - определение (ре) гидратации содержит следующие слова:Hydrating an object is taking an object that exists in memory, that doesn't yet contain any domain data ("real" data), and then populating it with domain data (such as from a database, from the network, or from a file system).
pxsx

3

Основы Сначала

Byte Stream - поток данных - это последовательность данных. Входной поток - читает данные из источника. Выходной поток - записывает данные в деситнацию. Байтовые потоки Java используются для побайтного ввода / вывода (8 бит за раз). Поток байтов подходит для обработки необработанных данных, таких как двоичные файлы. Потоки символов Java используются для выполнения ввода / вывода по 2 байта за раз, потому что символы хранятся с использованием соглашений Unicode в Java с 2 байтами для каждого символа. Символьный поток полезен при обработке (чтение / запись) текстовых файлов.

RMI (Remote Method Invocation) - API, обеспечивающий механизм для создания распределенного приложения в Java. RMI позволяет объекту вызывать методы для объекта, работающего в другой JVM.


И Сериализация, и Маршаллинг свободно используются как синонимы. Здесь мало различий.

Сериализация - данные-члены объекта записываются в двоичную форму или байтовый поток (а затем могут записываться в файл / память / базу данных и т. Д.). Никакая информация о типах данных не может быть сохранена после записи элементов данных объекта в двоичную форму.

введите описание изображения здесь

Marshalling - объект сериализуется (в байтовый поток в двоичном формате) с подключенным типом данных + кодовая база, а затем передается удаленный объект (RMI) . Маршаллинг преобразует тип данных в заранее определенное соглашение об именах, чтобы его можно было восстановить по исходному типу данных. введите описание изображения здесь

Так что сериализация является частью Marshalling.

CodeBase - это информация, которая сообщает получателю объекта, где можно найти реализацию этого объекта. Любая программа, которая думает, что может когда-либо передать объект другой программе, которая, возможно, не видела его раньше, должна установить кодовую базу, чтобы получатель мог знать, откуда загрузить код, если у него нет кода, доступного локально. При десериализации объекта получатель извлечет из него кодовую базу и загрузит код из этого местоположения. (Скопировано из ответа @Nasir)

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

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

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


1

Маршалинг на самом деле использует процесс сериализации, но основное отличие состоит в том, что в сериализации только элементы данных и сам объект сериализуются не в сигнатурах, а в базе кода Marshalling Object + (его реализация) также преобразуются в байты.

Маршаллинг - это процесс преобразования объекта Java в объекты XML с использованием JAXB, чтобы его можно было использовать в веб-службах.


0

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

NB - Java RMI также содержит поддержку для транспортировки классов, которые отсутствуют в получателе ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.