web-dev-qa-db-ja.com

Javaのシリアル化はどのように機能し、他の永続化手法の代わりにいつ使用する必要がありますか?

私は最近、仕事と個人の両方のプロジェクトでJavaのシリアル化についてもっと学び、一般的にテストしようとしています。Javaについて知れば知るほど、好きではなくなると言わざるを得ません。これは誤った情報が原因である可能性があります。そのため、次の2つのことを皆さんにお願いしています。

1:バイトレベルで、シリアル化は、シリアル化された値をあるクラスと照合する方法をどのように知っていますか?

ここでの私の問題の1つは、値「one」、「two」、「three」を含むArrayListを使用して小さなテストを行ったことです。シリアル化後、バイト配列は78バイトを要しました。これは、このような少量の情報(19 + 3 + 3 + 4バイト)では非常に多いようです。確かにいくらかのオーバーヘッドがあるはずですが、これは私の2番目の質問につながります:

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で標準になっていること以外に、シリアル化の本当の利点は何ですか?

39
Esko

私は個人的に、Javaの「組み込み」シリアル化を避けようとします。

  • 他のプラットフォームには移植できません
  • それほど効率的ではありません
  • それは壊れやすいです-クラスの複数のバージョンに対処するためにそれを取得することはやや注意が必要です。注意しない限り、コンパイラを変更してもシリアル化が壊れる可能性があります。

実際のバイトの意味の詳細については、 Java Object Serialization Specification を参照してください。

次のようなさまざまな選択肢があります。

(免責事項:私はGoogleで働いており、20%プロジェクトとしてProtocol BuffersをC#に移植しているので、明らかにそれは良い技術だと思います:)

クロスプラットフォーム形式は、明らかな理由から、ほとんどの場合、プラットフォーム固有の形式よりも制限が厳しくなります。たとえば、Protocol Buffersのネイティブタイプのセットはかなり限られていますが、相互運用性は非常に便利です。また、下位互換性と上位互換性など、バージョン管理の影響を考慮する必要があります。テキスト形式は通常、手動で編集できますが、空間と時間の両方で効率が低下する傾向があります。

基本的に、要件を注意深く検討する必要があります。

47
Jon Skeet

シリアル化の主な利点は、非常に使いやすく、比較的高速で、実際のJavaオブジェクトメッシュを保持することです。

ただし、実際にはデータの保存に使用することを意図したものではなく、主にさまざまなJVMインスタンスがRMIプロトコルを使用してネットワーク経由で通信するための方法であることを理解する必要があります。

9

シリアル化されたオブジェクトに使用される文法のファイル形式の説明については、Java Object Serialization Stream Protocol )を参照してください。

個人的には、組み込みのシリアル化は、アプリケーションの外部では関係のない短命のデータを永続化する(たとえば、セッションオブジェクトの状態をhttp-requestsに保存する)ために許容できると思います。

存続期間が長いデータ、またはアプリケーションの外部で使用する必要があるデータの場合、データベースに永続化するか、少なくともより一般的に使用される形式を使用します...

5
Argelbargel

Javaの組み込みシリアル化はどのように機能しますか?

オブジェクトをシリアル化する場合は常に、Java.io.Serializableインターフェイスを実装します。 コンパイラまたはJVMに何かを示すマーカーインターフェイスとして知られている)に実装しているにもかかわらず、実装するメソッドがないインターフェイス。したがって、JVMは、クラスがシリアライズ可能であると判断した場合、それらのクラスに対していくつかの前処理操作を実行します。操作は、次の2つのサンプルメソッドを追加します。

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を使用します。

4
Premraj

Java Object Serialization(JOS)の利点は、それが機能することです。JOSと同じように機能するツールもありますが、バイナリ形式ではなくXML形式を使用します。

長さについて:JOSは、各インスタンスの一部としてではなく、最初にいくつかのクラス情報を書き込みます。完全なフィールド名は一度記録され、その名前のリストへのインデックスがクラスのインスタンスに使用されます。これにより、クラスのインスタンスを1つだけ書き込むと出力が長くなりますが、複数の(異なる)インスタンスを書き込むと効率が向上します。あなたの例が実際にクラスを使用しているかどうかは私にはわかりませんが、これがJOSが予想よりも長い一般的な理由です。

ところで:これは偶然ですが、JSONはクラス名を記録するとは思わないので(例のように)、必要なことを実行できない可能性があります。

0
13ren

私は約1か月前にこのジレンマにぶつかりました( 私が尋ねた質問 を参照)。

私がそれから学んだ主な教訓は、必要な場合にのみ、他に選択肢がない場合にのみJavaシリアル化を使用することです。ジョンが言ったように、それは欠点がありますが、他のシリアル化技術ははるかに簡単で、速く、そしてよりポータブルです。

0
Yuval Adam

シリアル化とは、クラス内の構造化データをバイトコードのフラットな順序に並べて保存することを意味します。

通常、組み込みのJavaメソッド以外の手法を使用する必要があります。これはそのままで機能するように作られていますが、シリアル化されたクラスで将来コンテンツの変更や順序の変更が行われると、ロードできないため問題が発生します。それらを正しく。

0
berlindev

少量の情報をシリアル形式で格納する理由は比較的大きいのは、シリアル化するオブジェクトのクラスに関する情報を格納するためです。リストの複製を保存すると、ファイルがそれほど大きくなっていないことがわかります。同じオブジェクトを2回保存すると、違いはわずかです。

重要な長所は次のとおりです。比較的使いやすく、非常に高速で、進化することができます(XMLと同じように)。ただし、データはかなり不透明で、Javaのみであり、データをクラスに緊密に結合し、信頼できないデータは簡単にDoSを引き起こす可能性があります。単に平手打ちするのではなく、シリアル化された形式について考える必要がありますimplements Serializable どこにでも。