Jaka jest różnica między serializacją a marshalingiem?

Odpowiedzi:

404

Tworzenie i serializacja są luźne synonimiczne w kontekście zdalnego wywoływania procedur, ale semantycznie odmienne w zależności od celu.

W szczególności marshaling polega na przekazywaniu parametrów z miejsca na miejsce, podczas gdy serializacja polega na kopiowaniu danych strukturalnych do lub z prymitywnej postaci, takiej jak strumień bajtów. W tym sensie serializacja jest jednym ze sposobów przeprowadzania zestawiania, zwykle implementując semantykę według wartości.

Możliwe jest również uporządkowanie obiektu przez odniesienie, w którym to przypadku dane „na przewodzie” są po prostu informacją o lokalizacji oryginalnego obiektu. Jednak taki obiekt może nadal podlegać serializacji wartości.

Jak wspomina @Bill, mogą istnieć dodatkowe metadane, takie jak lokalizacja bazy kodu, a nawet kod implementacji obiektu.

Jeffrey Hantin
źródło
3
Czy istnieje słowo, które oznacza serializację i deserializację w tym samym czasie? Potrzebujesz nazwy interfejsu z tymi metodami.
raffian
1
@raffian, czy masz na myśli interfejs zaimplementowany przez obiekt poddany serializacji i deserializacji, czy przez obiekt odpowiedzialny za zarządzanie procesem? Sugerowane przeze mnie słowa kluczowe to odpowiednio „Serializable” i „Formatter”; udekoruj wiodącymi Izmianami wielkich liter i tak dalej, jeśli to konieczne.
Jeffrey Hantin
@JeffreyHantin Chodzi mi o obiekt odpowiedzialny za zarządzanie procesem; Używam teraz ISerializera, ale to tylko połowa racji :)
Rafael
6
@raffian w telekomunikacji nazywamy komponent szeregujący i deserializujący „SerDes” lub „serdes”, zwykle wymawiane sir-dez lub sir-deez w zależności od preferencji. Przypuszczam, że w swojej budowie jest podobny do „modemu” (tj. „Modulatora-demodulatora”).
davidA
2
@naki jest to branża - jeśli spojrzysz na szybkie karty danych FPGA, będą one wspominać o funkcjonalności SERDES, chociaż wszystkie są dość nowoczesne, sięgające lat 90. Google NGrams sugeruje, że stał się bardziej popularny w latach 80., chociaż znalazłem instancję w arkuszu danych IBM z 1970 r.
davidA
207

Oba mają jedną wspólną cechę - serializację obiektu. Serializacja służy do przesyłania lub przechowywania obiektów. Ale:

  • Serializacja: podczas serializacji obiektu tylko dane elementu w tym obiekcie są zapisywane w strumieniu bajtów; nie kod, który faktycznie implementuje obiekt.
  • Marshalling: Termin Marshalling jest używany, gdy mówimy o przekazywaniu obiektu do obiektów zdalnych (RMI) . W Marshalling Obiekt jest szeregowany (dane członka są serializowane) + Codebase jest dołączony.

Tak więc serializacja jest częścią Marshalling.

CodeBase to informacja, która informuje odbiorcę Object, gdzie można znaleźć implementację tego obiektu. Każdy program, który myśli, że może kiedykolwiek przekazać obiekt innemu programowi, który mógł go wcześniej nie widzieć, musi ustawić bazę kodu, aby odbiorca wiedział, skąd pobrać kod, jeśli kod nie jest dostępny lokalnie. Po deserializacji obiektu odbiornik pobierze z niego bazę kodu i załaduje kod z tej lokalizacji.

Nasir Ali
źródło
45
+1 za zdefiniowanie, co w tym kontekście oznacza CodeBase
Omar Salem
2
Zdarzają się marshaling bez serializacji. Zobacz Swing's invokeAndWaiti Forms's Invoke, które organizują synchroniczne wywołanie wątku interfejsu użytkownika bez udziału serializacji.
Jeffrey Hantin
2
„nie kod, który faktycznie implementuje obiekt”: Czy to oznacza metody klasowe? lub co to znaczy. Czy możesz to wyjaśnić?
Vishal Anand,
2
Co masz na myśli the implementation of this object? Czy możesz podać konkretny przykład Serializationi Marshalling?
Simin Jie
Marshalling bez serializacji ma miejsce w niektórych kontekstach, na przykład gdy wywołanie funkcji przenosi przepływ sterowania między modelami wątków (na przykład między współużytkowaną pulą wątków a biblioteką wątków z pojedynczym przypięciem) w ramach jednego procesu. Dlatego mówię, że są luźno synonimiczne w kontekście RPC .
Jeffrey Hantin,
94

Z artykułu w Wikipedii: Marshalling (informatyka) :

Termin „marszałek” jest uważany za synonim „serializować” w standardowej bibliotece Pythona 1 , ale terminy nie są synonimami w związanej z Javą RFC 2713:

„Marshal” oznacza obiekt, który zapisuje jego stan i bazę kodową w taki sposób, że gdy „marshalled object” jest „unmarshalled”, uzyskiwana jest kopia oryginalnego obiektu, prawdopodobnie poprzez automatyczne ładowanie definicji klas obiektu. Możesz sterować dowolnym obiektem, który można przekształcić do postaci szeregowej lub zdalnie. Marshalling jest jak serializacja, z tą różnicą, że marshalling zapisuje również bazy kodowe. Marshalling różni się od serializacji tym, że marshalling specjalnie traktuje odległe obiekty. (RFC 2713)

„Serializacja” obiektu oznacza konwersję jego stanu na strumień bajtów w taki sposób, że strumień bajtów może zostać przekształcony z powrotem w kopię obiektu.

Tak więc marshalling oprócz stanu zapisuje także bazę kodu obiektu w strumieniu bajtów.

Bill jaszczurka
źródło
1
Masz na myśli, że Obiekt, jeśli nie jest zserializowany, może po prostu mieć stan, nie będzie żadnej bazy kodu, tzn. Żadna z jego funkcji nie może zostać wywołana, to po prostu uporządkowany typ danych. A jeśli ten sam obiekt zostanie zmontowany, to będzie miał swoją bazę kodu wraz ze strukturą i kiedyś będzie mógł wywoływać swoje funkcje?
bjan
11
„Codebase” tak naprawdę nie oznacza „kodu”. Z „Jak działa Codebase ” ( goo.gl/VOM2Ym ) Codebase to po prostu sposób, w jaki programy wykorzystujące semantykę zdalnego zarządzania klasami RMI znajdują nowe klasy. Gdy nadawca obiektu serializuje ten obiekt w celu przesłania go do innej maszyny JVM, adnotuje szeregowany strumień bajtów informacją zwaną bazą kodu. Ta informacja informuje odbiorcę, gdzie można znaleźć implementację tego obiektu. Rzeczywista informacja przechowywana w adnotacji bazy kodu jest listą adresów URL, z których można pobrać plik klasy dla potrzebnego obiektu.
Giuseppe Bertone
2
@Neurone Ta definicja jest specyficzna dla Jini i RMI. „Codebase” to ogólny termin. en.wikipedia.org/wiki/Codebase
Bill the Lizard
2
@BilltheLizard Tak, ale ponieważ mówisz o marshallingu w Javie, błędem jest twierdzenie, że różnica między serializacją a marshallingiem polega na tym, że „marshalling zapisuje kod obiektu oprócz jego stanu” i prowadzi to do pytania bjan. Marshalling zapisuje „bazę kodu” oprócz stanu obiektu.
Giuseppe Bertone
19

Myślę, że główna różnica polega na tym, że Marshalling rzekomo obejmuje również bazę kodową. Innymi słowy, nie byłbyś w stanie sprowadzić i rozmontować obiektu w ekwiwalencie stanu innej klasy. .

Serializacja oznacza po prostu, że można zapisać obiekt i uzyskać stan równoważny, nawet jeśli jest to instancja innej klasy.

To powiedziawszy, są zazwyczaj synonimami.

Uri
źródło
2
Czy masz na myśli, że Obiekt, jeśli nie jest zserializowany, może po prostu mieć stan, nie będzie żadnej bazy kodu, tzn. Żadna z jego funkcji nie może zostać wywołana, to po prostu uporządkowany typ danych. A jeśli ten sam obiekt zostanie zmontowany, to będzie miał swoją bazę kodu wraz ze strukturą i można wywoływać jego funkcje?
bjan
18

Marshaling odnosi się do przekształcania podpisu i parametrów funkcji w tablicę jednobajtową. Specjalnie do celów RPC.

Serializacja częściej odnosi się do przekształcania całego obiektu / drzewa obiektów w tablicę bajtów. Marshaling dokonuje szeregowania parametrów obiektu w celu dodania ich do komunikatu i przekazania go przez sieć. * Serializacji można również użyć do przechowywania na dysku. *

H.Gankanda
źródło
11

Marshalling to reguła informująca kompilator, w jaki sposób dane będą reprezentowane w innym środowisku / systemie; Na przykład;

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

jak widać dwie różne wartości ciągu reprezentowane jako różne typy wartości.

Serializacja przekształci tylko treść obiektu, a nie reprezentację (pozostanie taka sama) i będzie przestrzegać zasad serializacji (co eksportować lub nie). Na przykład wartości prywatne nie będą serializowane, wartości publiczne tak, a struktura obiektu pozostanie taka sama.

Teoman Shipahi
źródło
7

Oto bardziej szczegółowe przykłady obu:

Przykład serializacji:

#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;
}

W serializacji dane są spłaszczane w sposób, który można później przechowywać i spłaszczać.

Demo Marshalling:

(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);    
}

W zestawianiu danych niekoniecznie trzeba spłaszczyć, ale należy je przekształcić w inną alternatywną reprezentację. wszystkie castingi to zebranie, ale nie wszystkie zebranie to zrzucenie.

Marshaling nie wymaga dynamicznej alokacji, może być tylko transformacją między strukturami. Na przykład możesz mieć parę, ale funkcja oczekuje, że pierwszy i drugi element pary będą na odwrót; rzutowanie / memcpy jednej pary na drugą nie spełni zadania, ponieważ fst i snd zostaną odwrócone.

#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;
}

Koncepcja marszowania staje się szczególnie ważna, gdy zaczniesz zajmować się oznaczonymi związkami wielu typów. Na przykład może być trudno uzyskać silnik JavaScript, który wydrukuje „ciąg c”, ale możesz poprosić go o wydrukowanie zawiniętego ciągu c. Lub jeśli chcesz wydrukować ciąg z środowiska wykonawczego JavaScript w środowisku wykonawczym Lua lub Python. Wszystkie są strunami, ale często nie mogą się dogadać bez organizowania.

Niedogodnością, którą ostatnio miałem, było to, że JScript tablicuje marszałka do C # jako „__ComObject” i nie ma udokumentowanego sposobu zabawy z tym obiektem. Mogę znaleźć adres, pod którym się znajduje, ale tak naprawdę nie wiem nic więcej na ten temat, więc jedynym sposobem, aby naprawdę to rozgryźć, jest wbić go w jakikolwiek możliwy sposób i mam nadzieję znaleźć przydatne informacje na jego temat. Dzięki temu łatwiej jest utworzyć nowy obiekt z bardziej przyjaznym interfejsem, takim jak Scripting.Dictionary, skopiować do niego dane z obiektu tablicy JScript i przekazać ten obiekt do C # zamiast domyślnej tablicy 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);
        }
    }
}

powyżej drukuje „__ComObject”, który jest nieco czarną skrzynką z punktu widzenia C #.

Inną ciekawą koncepcją jest to, że potrafisz rozumieć, jak pisać kod, i komputer, który umie wykonywać instrukcje, więc jako programista skutecznie zestawiasz koncepcję tego, co chcesz, aby komputer robił od mózgu do programu wizerunek. Gdybyśmy mieli wystarczająco dobrych marshallerów, moglibyśmy po prostu pomyśleć o tym, co chcemy zrobić / zmienić, a program zmieniłby to w ten sposób bez pisania na klawiaturze. Tak więc, jeśli możesz mieć sposób na przechowywanie wszystkich fizycznych zmian w mózgu przez kilka sekund, w których naprawdę chcesz napisać średnik, możesz połączyć te dane w sygnał, aby wydrukować średnik, ale to ekstremalne.

Dmitry
źródło
4

Marshalling odbywa się zwykle pomiędzy stosunkowo ściśle powiązanymi procesami; serializacja niekoniecznie ma takie oczekiwania. Tak więc, na przykład podczas zestawiania danych między procesami, możesz po prostu wysłać ODNIESIENIE do potencjalnie drogich danych do odzyskania, podczas gdy w przypadku serializacji chcesz zapisać wszystko, aby poprawnie odtworzyć obiekt (-y) po deserializacji.

Paul Sonier
źródło
4

Moje rozumienie marshallingu różni się od innych odpowiedzi.

Serializacja:

Aby wyprodukować lub nawodnić drutową wersję grafu obiektowego z wykorzystaniem konwencji.

Przetaczanie:

Aby utworzyć lub nawodnić wersję w postaci wykresu obiektowego za pomocą pliku odwzorowania, aby można było dostosować wyniki. Narzędzie może zacząć od przestrzegania konwencji, ale istotną różnicą jest możliwość dostosowania wyników.

Pierwszy rozwój kontraktu:

Marshalling jest ważny w kontekście pierwszego opracowania kontraktu.

  • Możliwe jest wprowadzanie zmian w wewnętrznym grafie obiektowym, przy jednoczesnym zachowaniu stabilności interfejsu zewnętrznego w czasie. W ten sposób wszyscy subskrybenci usługi nie będą musieli być modyfikowani dla każdej trywialnej zmiany.
  • Możliwe jest mapowanie wyników w różnych językach. Na przykład z konwencji nazw właściwości jednego języka („nazwa_właściwości”) na inny („nazwa_właściwości”).
Jasper Blues
źródło
1
// Czy mogę dowiedzieć się więcej o tym, co konkretnie „nawodnienie” oznacza w tej odpowiedzi @JasperBlues? Chyba nie chodzi tylko o jedzenie dla astronautów.
Nathan Basanese
@NathanBasanese zgodnie z tą odpowiedzią - stackoverflow.com/a/6991192/5101816 - definicja (ponownego) nawodnienia zawiera następujące słowa: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

Najpierw podstawy

Bajt - strumień to sekwencja danych. Strumień wejściowy - odczytuje dane ze źródła. Strumień wyjściowy - zapisuje dane do desitnation. Strumienie bajtowe Java są używane do wykonywania bajtów bajt po wejściu / wyjściu (8 bitów na raz). Strumień bajtów jest odpowiedni do przetwarzania surowych danych, takich jak pliki binarne. Strumienie znaków Java są używane do wykonywania 2 bajtów wejściowych / wyjściowych, ponieważ znaki są przechowywane w Javie przy użyciu konwencji Unicode z 2 bajtami na każdy znak. Strumień znaków jest przydatny podczas przetwarzania (odczytu / zapisu) plików tekstowych.

RMI (Remote Method Invocation) - interfejs API, który zapewnia mechanizm tworzenia aplikacji rozproszonej w Javie. RMI pozwala obiektowi wywoływać metody na obiekcie działającym w innym JVM.


Zarówno Serializacja, jak i Marshalling są luźno używane jako synonimy. Oto kilka różnic.

Serializacja - elementy danych obiektu są zapisywane w formie binarnej lub w strumieniu bajtów (a następnie mogą być zapisywane w pliku / pamięci / bazie danych itp.). Żadne informacje o typach danych nie mogą zostać zachowane, gdy elementy danych obiektu zostaną zapisane w formie binarnej.

wprowadź opis zdjęcia tutaj

Marshalling - Obiekt jest szeregowany (do bajtu strumienia w formacie binarnym) z dołączonym typem danych + Codebase, a następnie przekazywany Obiekt zdalny (RMI) . Marshalling przekształci typ danych w z góry określoną konwencję nazewnictwa, aby można go było zrekonstruować w odniesieniu do początkowego typu danych. wprowadź opis zdjęcia tutaj

Tak więc serializacja jest częścią Marshalling.

CodeBase to informacja, która informuje odbiorcę Object, gdzie można znaleźć implementację tego obiektu. Każdy program, który myśli, że może kiedykolwiek przekazać obiekt do innego programu, który mógł go wcześniej nie widzieć, musi ustawić bazę kodu, aby odbiorca wiedział, skąd pobrać kod, jeśli kod nie jest dostępny lokalnie. Po deserializacji obiektu odbiornik pobierze z niego bazę kodu i załaduje kod z tej lokalizacji. (Skopiowano z odpowiedzi @Nasir)

Serializacja jest prawie jak głupi zrzut pamięci używanej przez obiekt (obiekty), podczas gdy Marshalling przechowuje informacje o niestandardowych typach danych.

W pewien sposób serializacja dokonuje marshallingu z implikacją przekazywania wartości, ponieważ nie są przekazywane żadne informacje o typie danych, tylko pierwotna postać jest przekazywana do strumienia bajtów.

Serializacja może mieć pewne problemy związane z big-endian, small-endian, jeśli strumień przechodzi z jednego systemu operacyjnego do drugiego, jeśli inny system operacyjny ma różne sposoby reprezentowania tych samych danych. Z drugiej strony marshalling jest w porządku do migracji między systemami operacyjnymi, ponieważ wynikiem jest reprezentacja wyższego poziomu.

Om Sao
źródło
1

Marshaling faktycznie używa procesu serializacji, ale główna różnica polega na tym, że w serializacji tylko członkowie danych i sam obiekt są serializowane, a nie podpisy, ale w Marshalling Object + kod bazy (jego implementacja) również zostaną przekształcone w bajty.

Marshalling to proces konwersji obiektu Java na obiekty XML za pomocą JAXB, aby można go było używać w usługach internetowych.

Aman Goel
źródło
0

Pomyśl o nich jak o synonimach, obaj mają producenta, który wysyła rzeczy do konsumenta ... Na końcu pola instancji są zapisywane w strumieniu bajtów, a drugi koniec przeciwnie i odwraca się w tych samych instancjach.

Uwaga - Java RMI zawiera także obsługę klas transportowych, których brakuje odbiorcy ...

poseł.
źródło