2010-07-01 2 views
3

У меня есть очень большой объект, который я хочу сериализовать. Во время процесса сериализации он занимает около 130 МБ кучи в виде weblogic.utils.io.UnsyncByteArrayOutputStream. Я использую BufferedOutputStream для ускорения записи данных на диск, что сокращает время, в течение которого этот объект хранится в памяти.Можно ли буферизировать объекты во время сериализации Java?

Возможно ли использовать буфер для уменьшения размера объекта в памяти? Было бы хорошо, если бы был способ сериализовать его по x байтов за один раз и записать эти байты на диск.

Образец кода следует, если он используется. Там не так много, хотя я не думаю. Если это так, то должна быть полная копия в памяти объекта, который будет сериализован (и, следовательно, нет понятия буфера для сериализации), то я полагаю, что я застрял.

ObjectOutputStream tmpSerFileObjectStream = null; 
    OutputStream tmpSerFileStream = null; 
    BufferedOutputStream bufferedStream = null; 
    try { 

     tmpSerFileStream = new FileOutputStream(tmpSerFile); 
     bufferedStream = new BufferedOutputStream(tmpSerFileStream); 

     tmpSerFileObjectStream = new ObjectOutputStream(bufferedStream); 
     tmpSerFileObjectStream.writeObject(siteGroup); 
     tmpSerFileObjectStream.flush(); 

    } catch (InvalidClassException invalidClassEx) { 
     throw new SiteGroupRepositoryException(
       "Problem encountered with class being serialised", invalidClassEx); 
    } catch (NotSerializableException notSerializableEx) { 
     throw new SiteGroupRepositoryException(
       "Object to be serialized does not implement " + Serializable.class, 
       notSerializableEx); 
    } catch (IOException ioEx) { 
     throw new SiteGroupRepositoryException(
       "Problem encountered while writing ser file", ioEx); 
    } catch (Exception ex) { 
     throw new SiteGroupRepositoryException(
       "Unexpected exception encountered while writing ser file", ex); 
    } finally { 
     if (tmpSerFileObjectStream != null) { 
      try { 
       tmpSerFileObjectStream.close(); 
       if(null!=tmpSerFileStream)tmpSerFileStream.close(); 
       if(null!=bufferedStream)bufferedStream.close(); 
      } catch (IOException ioEx) { 
       logger.warn("Exception caught on trying to close ser file stream", ioEx); 
      } 
     } 
    } 
+0

Можете ли вы опубликовать некоторый пример кода вашей логики сериализации? Что-то здесь не складывается - откуда взялся бы этот веб-класс? –

ответ

0

Что такое объект "siteGroup", который вы пытаетесь сохранить? Я спрашиваю, потому что маловероятно, что какой-либо один объект имеет размер 130 МБ, если у него нет ginormous list/array/map/whatever в нем - и если это так, то ответ будет состоять в том, чтобы сохранить эти данные в базе данных.

Но если в объекте нет коллекции монстров, проблема в том, что дерево объектов содержит ссылки на объекты bagillion, а сериализация, конечно, делает глубокую копию (этот факт использовался как ярлык для реализации clone() много раз), поэтому все становится каталогизированным все сразу сверху вниз.

Если это проблема, тогда решение будет заключаться в реализации вашей собственной схемы сериализации, где каждый объект будет сериализован снизу вверх, возможно, в нескольких файлах, и только ссылки будут поддерживаться для других объектов, а не для всего вещь. Это позволит вам написать каждый объект отдельно, что будет иметь эффект: меньший объем памяти из-за записи данных в кусках.

Однако реализовать свою собственную сериализацию, такую ​​как реализация метода clone(), не все так просто. Так что это выгодная вещь.

+0

Он содержит огромную карту объектов, которые действительно сохраняются в базе данных. Сериализация предназначена только для скорости запуска, так как построение карты из базы данных занимает несколько часов, а не меньше минуты с диска. –

+0

Ах. Это может сделать вещи проще ... можете ли вы просто пройти через карту и сериализовать все эти объекты отдельно, затем очистить карту и сериализовать основной объект siteGroup? При запуске вы могли бы отменить процесс: построить карту, а затем поместить ее в объект. Это может немного уменьшить размер кучи. –

0

Почему занимают все эти байты в качестве несинхр выходного потока массива байт?

Это не так, как работает сериализация по умолчанию. У вас должен быть специальный код, чтобы сделать это. Решение: не надо.

+0

Weblogic.utils.io.UnsyncByteArrayOutputStream отображается в куче кучи, откуда я получил эту информацию. Эта процедура вызывает прерывистые ошибки из памяти, следовательно, вопрос. Я не думаю, что я могу многое сделать с тем, как Weblogic выбирает сериализацию. –

+0

@MarkChorley В этом вопросе нет кучи кучи. Если вы не указали важную информацию, не делайте этого. – EJP

0

Похоже, что любое время выполнения, которое вы используете, имеет менее реалистичную реализацию сериализации объектов, которая, вероятно, не имеет никакого контроля над.

Аналогичная жалоба упоминается здесь, хотя она довольно старая. http://objectmix.com/weblogic/523772-outofmemoryerror-adapter.html

Можете ли вы использовать более новую версию веб-журнала? Можете ли вы воспроизвести это в единичном тесте? Если да, попробуйте запустить его под другой JVM и посмотреть, что произойдет.

+0

Weblogic 9.2.3, и использование более новой версии, к сожалению, в ближайшее время не является вариантом. JDK 1.5.0.16, если это помогает. –

+1

Эта ошибка Java немного объясняет, как сериализация объектов работает под обложками. Он предлагает объяснение, почему весь объект должен храниться в буфере. Для вашего случая вам придется разделить большой объект на более мелкие и вызвать функцию сброса() в ObjectOutputStream, чтобы разбить его. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4363937 – wolfcastle

0

Я не знаю, о WebLogic (то есть - JRockit я полагаю) сериализации в частности: честно говоря, я не вижу причин для использования ByteArrayOutputStreams ...

Вы можете реализовать java.io.Externalizable, если вам нужно больше контроля на как ваш объект сериализуется - или переключитесь на совершенно другую систему сериализации (например: Terracotta), если вы не хотите самостоятельно писать методы чтения/записи (если у вас много больших классов).

2

Это не так на многих уровнях. Это массовое злоупотребление сериализацией. Сериализация в основном предназначена для временного хранения объекта. Например,

  1. объекты сеанса между серверами tomcat перезапускаются.
  2. передача объектов между JVM, (балансировка нагрузки на веб-сайте)

сериализации в Java не делает никаких усилий, чтобы справиться с длительного хранения объектов (Нет поддержки версий) и не может обрабатывать большие объекты хорошо.

Для чего-то настолько большого, я хотел бы предложить некоторые исследования первым:

  1. Убедитесь, что вы не пытаетесь сохраняться всю JVM Heap.
  2. Посмотрите на переменные-члены, которые могут быть помечены как «переходные», чтобы не включать их в сериализацию (возможно, у вас есть ссылки на объекты обслуживания)
  3. Рассмотрите возможность утечки памяти, и объект чрезмерно большой.

Если все действительно правильно, вам придется исследовать альтернативы java.io.Serialization. Принимая больше контроля через java.io.Externalization может работать. Но я бы предложил что-то вроде json или xml-представления.

Update:

Исследовать:

  1. google's protocol buffer
  2. facebook's Thrift
  3. Avro
  4. Cisco's Etch

Take a look at this benchmarkings as well.

+0

Все три этих пункта были рассмотрены и устранены. Уменьшение размера объекта в памяти не является простым - в нем содержится примерно 500 000 элементов контента, кэшированных из CMS с минимальными данными, хранящимися в каждом из них.Он сохраняется на диске, как вы вывели, для ускорения перезапуска приложений. Мне нравится звук альтернативного представления, так как это уменьшит размер на диске. Но будет ли это иметь значение для памяти, занятой во время сериализации? –

+1

Проблема с перекрестными перезапусками заключается в том, что, предположительно, вы только перезагружаете сервер, потому что есть новая версия кода. Новая версия означает, что сериализованная старая версия не может быть надежно десериализована. Так эффективно ничего не получается. – Pat

Смежные вопросы