0

XStream を使用して XML をシリアライズ/デシリアライズします...OutOfMemory 例外が発生しました。

まず、サーバーに 500MB が割り当てられているため、エラーが発生する理由がわかりません。

問題は、トラブルを回避するためにどのような変更を加える必要があるかということです。この実装の規模を確実にしたいと考えています。

現在、各オブジェクトが最大 50 バイト、最大 60K のオブジェクトがあります。60K POJO をメモリにロードし、それらを String にシリアライズして、 を使用して Web サービスに送信しますHttpClient。受信時に文字列全体を取得し、POJO に変換します。XML/オブジェクト階層は次のようになります。

<root>
    <meta>
       <date>10/10/2009</date>
       <type>abc</type>
    </meta>

    <data>
        <field>x</field>
    </data>

    [thousands of <data>]
</root>

POJOをメモリに保存せ、内容を単一の文字列に書き込まないことが最善の方法だと思います。代わりに、個々<data>の POJO をストリームに書き込む必要があります。XStreamはこれをサポートしていますが、この<meta>要素はサポートされていないようです。データは次の形式である必要があります。

<root> 
    <data>
        <field>x</field>
    </data>

    [thousands of <data>]
</root>

では、ツリー全体をストリーミングする最も簡単な方法は何ですか?

4

4 に答える 4

3

POJO を巨大な文字列にシリアライズしてから、その文字列を書き出すことは絶対に避けたいと考えています。XStream API を使用して、POJO を直接 OutputStream にシリアル化します。今年の初めに、200 ~ 300Mb の XML ドキュメントを生成し、OutOfMemoryErrors を取得していることに気付いたとき、同じ状況に遭遇しました。切り替えはとても簡単でした。

もちろん、読む側も同じです。XML を文字列に読み取って、その文字列から逆シリアル化するように XStream に要求しないでください。InputStream から直接逆シリアル化します。

<meta>要素と要素をシリアル化できないという2番目の問題について言及してい<data>ます。私は通常、次の順序でより複雑な構造をシリアル化するため、これは XStream の問題または制限ではないと思います。

<myobject>
    <item>foo</item>
    <anotheritem>foo</anotheritem>
    <alist>
        <alistitem>
            <value1>v1</value1>
            <value2>v2</value2>
            <value3>v3</value3>
            ...
        </alistitem>
        ...
        <alistitem>
            <value1>v1</value1>
            <value2>v2</value2>
            <value3>v3</value3>
            ...
        </alistitem>
    </alist>
    <anotherlist>
        <anotherlistitem>
            <valA>A</valA>
            <valB>B</valB>
            <valC>C</valC>
            ...
        </anotherlistitem>
        ...
    </anotherlist>
</myobject>

ネストされたリストのシリアル化と逆シリアル化にも成功しました。

于 2009-12-16T04:47:52.370 に答える
2

ここで何が問題なのかわからない...あなたはそのウェブページであなたの答えを見つけました。

あなたが提供したリンクのサンプルコードは、次のことを示唆しています:

Writer someWriter = new FileWriter("filename.xml");

ObjectOutputStream out = xstream.createObjectOutputStream(someWriter, "root");
out.writeObject(dataObject);
// iterate over your objects...
out.close();

ほぼ同じですが、Reader for Writer と Input for Output を使用して読み取ります。

Reader someReader = new FileReader("filename.xml");

ObjectInputStream in = xstream.createObjectInputStream(someReader);
DataObject foo = (DataObject)in.readObject();
// do some stuff here while there's more objects...
in.close();
于 2009-12-16T02:04:20.140 に答える
0

Visual VMEclipse Memory Analyzerなどのツールを使用して、メモリ リークや問題がないことを確認することをお勧めします。

また、各オブジェクトが 50 バイトであることはどのようにしてわかりますか? そうは思えません。

于 2009-12-16T01:56:54.883 に答える
0

XMLStreamWriter (または XStream) を使用してシリアライズします。好きなように書き込むことができます。文字列全体ではなく入力ストリームを取得するオプションがある場合は、SAXParser を使用します。これはイベント ベースであり、実装は少しぎこちないかもしれませんが、スローされた任意の XML を読み取ることができます。 XML が巨大な場合 (SAXParser で 2GB 以上の XML ファイルを解析しました)。

補足として、XML パーサーには文字列ではなくバイナリ データを送信する必要があります。XML パーサーは、XML シーケンスの先頭にある xml タグを介して、次に来るバイト配列のエンコーディングを読み取ります。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>

文字列はすでに何かでエンコードされています。String を作成する前に、XML で元のストリームを解析することをお勧めします。

于 2009-12-16T05:13:50.357 に答える