Лучший подход для сериализации XML для потоковой передачи с Java? - PullRequest
0 голосов
/ 16 декабря 2009

Мы сериализуем / десериализуем XML, используя XStream ... и только что получили исключение OutOfMemory.

Во-первых, я не понимаю, почему мы получаем ошибку, поскольку 500 МБ выделены для сервера.

Вопрос в том, какие изменения мы должны сделать, чтобы избежать неприятностей? Мы хотим обеспечить масштабирование этой реализации.

В настоящее время у нас есть ~ 60K объектов, каждый ~ 50 байтов. Мы загружаем 60K POJO в память и сериализуем их в строку, которую отправляем веб-сервису, используя 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 ]

3 голосов
/ 16 декабря 2009

Вы определенно хотите избежать сериализации ваших POJO в огромную строку, а затем записывать эту строку. Используйте API-интерфейсы XStream для сериализации POJO непосредственно в ваш OutputStream. Ранее в этом году я столкнулся с той же ситуацией, когда обнаружил, что я генерирую XML-документы объемом 200-300 МБ и получаю OutOfMemoryErrors. Сделать выключатель было очень легко.

И, конечно же, для читающей стороны. Не считывайте XML в строку и не просите XStream десериализовать из этой строки: десериализовать непосредственно из InputStream.

Вы упомянули вторую проблему, касающуюся невозможности сериализации элемента <meta> и элементов <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>

Я также успешно сериализовал и десериализовал вложенные списки.

2 голосов
/ 16 декабря 2009

Не уверен, в чем проблема ... вы нашли ответ на этой веб-странице.

Пример кода по предоставленной вами ссылке предлагает:

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

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

и для чтения почти идентичного, но с Reader для Writer и ввода для вывода:

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();
0 голосов
/ 16 декабря 2009

Используйте XMLStreamWriter (или XStream) для его сериализации, вы можете написать на нем все, что захотите. Если у вас есть возможность получить входной поток вместо всей строки, используйте SAXParser, он основан на событиях и, хотя реализация может быть немного неуклюжей, вы сможете прочитать любой XML, который вам брошен, даже если это огромный XML (у меня есть 2 ГБ + больше файлов XML с SAXParser).

В качестве примечания следует отправлять двоичные данные, а не строку, в синтаксический анализатор XML. Синтаксические анализаторы XML будут считывать кодировку байтового массива, который будет следовать через тег XML в начале последовательности XML:

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

Строка уже закодирована во что-то. Лучше дать XML-анализу исходный поток перед созданием с ним строки.

0 голосов
/ 16 декабря 2009

Я бы предложил использовать такие инструменты, как Visual VM или Eclipse Memory Analyzer , чтобы убедиться, что у вас нет утечки памяти / проблемы.

Кроме того, откуда вы знаете, что каждый объект занимает 50 байт? Это вряд ли звучит.

...