いくつかの分散技術(RPCなど)の観点から、「マーシャリング」という用語が使用されていることは知っていますが、シリアル化との違いがわかりません。どちらもオブジェクトを一連のビットに変換していませんか?
13 に答える
マーシャリングとシリアル化は、リモートプロシージャコールのコンテキストでは大まかに同義ですが、意図の問題として意味的に異なります。
特に、マーシャリングはここからそこまでパラメータを取得することであり、シリアル化は構造化データをバイトストリームなどのプリミティブ形式との間でコピーすることです。この意味で、シリアル化はマーシャリングを実行する1つの手段であり、通常は値渡しのセマンティクスを実装します。
オブジェクトを参照によってマーシャリングすることも可能です。その場合、「ネットワーク上の」データは単に元のオブジェクトの位置情報です。ただし、そのようなオブジェクトは、値のシリアル化に適している場合があります。
@Billが言及しているように、コードベースの場所やオブジェクト実装コードなどの追加のメタデータが存在する場合があります。
どちらも共通点が1つあります。それは、オブジェクトのシリアル化です。シリアル化は、オブジェクトを転送または保存するために使用されます。だが:
- シリアル化:オブジェクトをシリアル化すると、そのオブジェクト内のメンバーデータのみがバイトストリームに書き込まれます。オブジェクトを実際に実装するコードではありません。
- マーシャリング:マーシャリングという用語は、オブジェクトをリモートオブジェクト(RMI)に渡す ことについて話すときに使用されます。マーシャリングでは、オブジェクトがシリアル化されます(メンバーデータがシリアル化されます)+コードベースが添付されます。
したがって、シリアル化はマーシャリングの一部です。
CodeBaseは、このオブジェクトの実装がどこにあるかをObjectの受信者に通知する情報です。オブジェクトを以前に見たことがない別のプログラムに渡す可能性があると考えるプログラムは、コードベースを設定する必要があります。これにより、受信者は、ローカルで利用可能なコードがない場合に、コードをダウンロードする場所を知ることができます。受信者は、オブジェクトを逆シリアル化すると、オブジェクトからコードベースをフェッチし、その場所からコードをロードします。
マーシャリング(コンピューターサイエンス)ウィキペディアの記事から:
「マーシャル」という用語は、Python標準ライブラリ1では「シリアライズ」と同義であると見なされますが、Java関連のRFC2713ではこの用語は同義ではありません。
オブジェクトを「マーシャリング」するということは、マーシャリングされたオブジェクトが「マーシャリングされていない」ときに、おそらくオブジェクトのクラス定義を自動的にロードすることによって、元のオブジェクトのコピーが取得されるように、その状態とコードベースを記録することを意味します。シリアル化可能またはリモートの任意のオブジェクトをマーシャリングできます。マーシャリングは、コードベースも記録することを除けば、シリアル化に似ています。マーシャリングは、リモートオブジェクトを特別に処理するという点で、シリアル化とは異なります。(RFC 2713)
オブジェクトを「シリアル化」するということは、バイトストリームをオブジェクトのコピーに戻すことができるように、その状態をバイトストリームに変換することを意味します。
したがって、マーシャリングは、オブジェクトの状態に加えて、オブジェクトのコードベースもバイトストリームに保存します。
主な違いは、マーシャリングにはおそらくコードベースも含まれるということだと思います。つまり、オブジェクトを別のクラスの状態に相当するインスタンスにマーシャリングおよびアンマーシャリングすることはできません。
シリアル化とは、オブジェクトが別のクラスのインスタンスであっても、オブジェクトを保存して同等の状態を再取得できることを意味します。
そうは言っても、それらは通常同義語です。
マーシャリングとは、関数のシグネチャとパラメータを1バイト配列に変換することです。 特にRPCの目的で。
多くの場合、シリアル化とは、オブジェクト/オブジェクトツリー全体をバイト配列に変換すること です。マーシャリングは、オブジェクトパラメータをシリアル化してメッセージに追加し、ネットワークに渡します。 *シリアル化はディスクへの保存にも使用できます。*
基本を最初に
バイトストリーム-ストリームは一連のデータです。入力ストリーム-ソースからデータを読み取ります。出力ストリーム-宛先にデータを書き込みます。Javaバイトストリームは、バイトごとに(一度に8ビット)入出力を実行するために使用されます。バイトストリームは、バイナリファイルなどの生データの処理に適しています。Java文字ストリームは、一度に2バイトの入出力を実行するために使用されます。これは、文字がJavaのUnicode規則を使用して格納され、各文字が2バイトであるためです。文字ストリームは、テキストファイルを処理(読み取り/書き込み)するときに役立ちます。
RMI(Remote Method Invocation)-Javaで分散アプリケーションを作成するメカニズムを提供するAPI。RMIを使用すると、オブジェクトは別のJVMで実行されているオブジェクトのメソッドを呼び出すことができます。
シリアル化とマーシャリングはどちらも同義語として大まかに使用されます。ここにいくつかの違いがあります。
シリアル化-オブジェクトのデータメンバーは、バイナリ形式またはバイトストリームに書き込まれます(その後、ファイル/メモリ/データベースなどに書き込むことができます)。オブジェクトデータメンバーがバイナリ形式で書き込まれると、データ型に関する情報を保持できなくなります。
マーシャリング-オブジェクトは、データ型+コードベースがアタッチされた状態で(バイナリ形式のバイトストリームに)シリアル化されてから、リモートオブジェクト(RMI)に渡されます。マーシャリングは、データ型を所定の命名規則に変換して、最初のデータ型に関して再構築できるようにします。
したがって、シリアル化はマーシャリングの一部です。
CodeBaseは、このオブジェクトの実装がどこにあるかをObjectの受信者に通知する情報です。オブジェクトを以前に見たことがない別のプログラムに渡す可能性があると考えるプログラムは、コードベースを設定する必要があります。これにより、受信者は、ローカルで利用可能なコードがない場合に、コードをダウンロードする場所を知ることができます。受信者は、オブジェクトを逆シリアル化すると、オブジェクトからコードベースをフェッチし、その場所からコードをロードします。(@Nasirの回答からコピー)
シリアル化は、オブジェクトによって使用されるメモリの愚かなメモリダンプのようなものですが、マーシャリングはカスタムデータ型に関する情報を格納します。
ある意味で、データ型の情報は渡されず、プリミティブ形式のみがバイトストリームに渡されるため、シリアル化は値渡しの実装でマーシャリングを実行します。
異なるOSが同じデータを表す異なる手段を持っている場合、ストリームが1つのOSから別のOSに移動する場合、シリアル化にはビッグエンディアン、スモールエンディアンに関連する問題が発生する可能性があります。一方、マーシャリングは、結果がより高レベルの表現であるため、OS間での移行にはまったく問題ありません。
マーシャリングは、データが別の環境/システムでどのように表現されるかをコンパイラーに指示するルールです。例えば;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
異なる値タイプとして表される2つの異なる文字列値を見ることができるように。
シリアル化はオブジェクトコンテンツのみを変換し、表現は変換せず(同じまま)、シリアル化のルール(何をエクスポートするか、何をエクスポートしないか)に従います。たとえば、プライベート値はシリアル化されず、パブリック値はyesであり、オブジェクト構造は同じままです。
両方のより具体的な例を次に示します。
シリアル化の例:
#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;
}
シリアル化では、データは後で保存およびフラット化解除できる方法でフラット化されます。
マーシャリングデモ:
(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);
}
マーシャリングでは、データを必ずしもフラット化する必要はありませんが、別の代替表現に変換する必要があります。すべてのキャスティングはマーシャリングですが、すべてのマーシャリングがキャスティングしているわけではありません。
マーシャリングでは、動的な割り当てを行う必要はありません。構造体間の変換にすることもできます。たとえば、ペアがある場合でも、関数はペアの1番目と2番目の要素が逆であることを想定しています。fstとsndが反転するため、あるペアを別のペアにキャスト/memcpyしても機能しません。
#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配列が「__ComObject」としてC#にマーシャリングされ、このオブジェクトで遊ぶための文書化された方法がないことでした。それがどこにあるのかはわかりますが、それについては他に何も知りません。そのため、実際にそれを理解する唯一の方法は、可能な限りそれを調べて、うまくいけばそれに関する有用な情報を見つけることです。そのため、Scripting.Dictionaryのような使いやすいインターフェイスを使用して新しいオブジェクトを作成し、JScript配列オブジェクトからそのオブジェクトにデータをコピーして、そのオブジェクトをJScriptのデフォルト配列ではなくC#に渡すことが簡単になります。
(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#の観点からはブラックボックスのようなものです。
もう1つの興味深い概念は、コードの記述方法を理解している可能性があり、命令の実行方法を知っているコンピューターがあるため、プログラマーとして、コンピューターに実行させたいことの概念を脳からプログラムに効果的にマーシャリングしていることです。画像。十分な数のマーシャラーがいれば、何をしたいのか、何を変更したいのかを考えるだけで、キーボードで入力しなくてもプログラムはそのように変更されます。したがって、本当にセミコロンを書きたい場所で、脳内のすべての物理的変化を数秒間保存する方法があれば、そのデータを信号にマーシャリングしてセミコロンを印刷することができますが、それは極端です。
マーシャリングは通常、比較的密接に関連するプロセス間で行われます。シリアル化は必ずしもその期待を持っているわけではありません。したがって、たとえば、プロセス間でデータをマーシャリングする場合、復元するために潜在的に高価なデータにREFERENCEを送信するだけでよいのに対し、シリアル化では、すべてを保存して、逆シリアル化されたときにオブジェクトを適切に再作成することができます。
マーシャリングについての私の理解は、他の答えとは異なります。
シリアル化:
規則を利用して、オブジェクトグラフのワイヤー形式バージョンを作成または再水和すること。
マーシャリング:
結果をカスタマイズできるように、マッピングファイルを利用してオブジェクトグラフのワイヤー形式バージョンを作成または再水和すること。ツールは、規則に従うことから始める場合がありますが、重要な違いは、結果をカスタマイズする機能です。
契約の最初の開発:
マーシャリングは、契約の最初の開発のコンテキスト内で重要です。
- 外部インターフェイスを長期間安定させながら、内部オブジェクトグラフに変更を加えることができます。このように、すべてのサービスサブスクライバーは、些細な変更のたびに変更する必要がありません。
- 異なる言語間で結果をマッピングすることが可能です。たとえば、ある言語のプロパティ名の規則('property_name')から別の言語('propertyName')へ。
シリアル化とマーシャリング
問題:オブジェクトはいくつかのプロセス(VM)に属しており、その存続期間は同じです
Serialisation
-オブジェクトの状態をバイトのストリーム(JSON、XML ...)に変換して、保存、共有、変換...
Marshalling
-が含まれていますSerialisation + codebase
。通常、これはRemote procedure call
(RPC)-> (Java RMI)によって使用され、リモートJavaプロセスJava Remote Method Invocation
でホストされているオブジェクトのメソッドを呼び出すことができます。
codebase
class definition
-ClassLoaderでダウンロードできる場所またはURLです。CLASSPATH
[About]はローカルコードベースとして
JVM -> Class Loader -> load class definition
java -Djava.rmi.server.codebase="<some_URL>" -jar <some.jar>
RMIの非常に単純な図

Serialisation - state
Marshalling - state + class definition
マーシャリングは実際にはシリアル化プロセスを使用しますが、主な違いは、シリアル化ではデータメンバーとオブジェクト自体のみがシリアル化され、署名ではなく、マーシャリングオブジェクト+コードベース(その実装)でもバイトに変換されることです。
マーシャリングは、JAXBを使用してJavaオブジェクトをxmlオブジェクトに変換し、Webサービスで使用できるようにするプロセスです。
それらを同義語と考えてください。どちらにも、コンシューマーにデータを送信するプロデューサーがあります...最後に、インスタンスのフィールドはバイトストリームに書き込まれ、もう一方の端は、同じインスタンスで逆になります。
注意-javaRMIには、受信者から欠落しているクラスを転送するためのサポートも含まれています...