2012-04-24 6 views
0

Я борюсь с проблемой, которую я использую в EOF-структуре Apple довольно долгое время. Похоже, что иногда, когда создается EOEnterpriseObject или втягивается в контекст редактирования из БД, EOF не отпускает память, которую объект потребляет, даже после того, как соответствующий объект предприятия, контекст редактирования и хранилище объектов расположены и удалены. Похоже, что большинство объектов обрабатываются EOF очень просто, но у меня есть 2 объекта, где EOF последовательно удерживает память, используемую объектами, до тех пор, пока приложение не будет перезапущено. Оба эти ОР потенциально очень большие (они содержат объект NSData, который используется для хранения вложения файла).Утечка памяти в WebObjects

Используя JProfiler, я обнаружил, что ссылка на проблему EOS хранится в массиве EODatabase._snapshots.

Мне было интересно, если бы у кого-то еще была аналогичная проблема с EOF и/или проектом Wonder. Поскольку я постоянно вижу проблему в двух разных сценариях, я надеюсь, что это будет довольно распространенным явлением, и поэтому имеет разрешение ...

Я использую последнюю библиотеку WebObjects (5.4.3) и последнюю версию Wonder библиотеки.

Ниже не мой точный код, но это самый маленький, можно пример, который до сих пор имеет место утечка памяти:

`

public WOActionResults createEmailHistoryEntry() throws MessagingException, IOException { 
    File emailFile = new File("Email_with_large_attachment.eml"); 
    javax.mail.Message message = EmailUtils.convertEmlToMessage(emailFile); 

    EOObjectStore osc = new ERXObjectStoreCoordinator(true); 
    EOEditingContext ec = ERXEC.newEditingContext(osc); 
    ec.lock(); 
    try { 
     EmailHistoryEntry historyEntry = (EmailHistoryEntry) EOUtilities.createAndInsertInstance(ec, EmailHistoryEntry.class.getSimpleName()); 
     EmailDataObject emailData = (EmailDataObject) EOUtilities.createAndInsertInstance(ec, EmailDataObject.class.getSimpleName()); 
     emailData.setEmailHistoryEntry(historyEntry); 

     ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 
     message.writeTo(byteStream); 
     NSData rawEmail = new NSData(byteStream.toByteArray()); 
     emailData.setRawEmail(rawEmail); 

     ec.saveChanges(); 
    } 
    finally { 
     ec.unlock(); 
     ec.dispose(); 
     osc.dispose(); 
    } 
    return null; 
} 

`

Я не знаю, что Я делаю там что-то необычное ... Если я запустил его несколько раз, потребление памяти будет расти примерно на 140 МБ каждый раз и в конечном итоге ударит ошибку из-за памяти.


2012-12-26 -`
Я сделал еще некоторые исследования по этому вопросу. Похоже, что проблема заключается в библиотеке Project Wonder, а не в библиотеке EOF. Я понимаю, что «проблема» может быть мной и/или моим пониманием, а не Wonder lib ... :)

Я создал тестовое приложение, которое дублирует проблему, которую я видел, и разместил ее на github: https://github.com/t-evans/memory-leak-test.git.

Приложение для тестирования в основном просто приложение по умолчанию, которое создает Eclipse при добавлении нового приложения Wonder. Изменения включают добавление одной строки в Application.java, большую часть кода в Main.java и, конечно же, файл модели. В настоящее время он настроен на подключение к базе данных postgres с именем «memleaktest».

Конфигурация запуска приложения имеет только два аргумента VM: «-Xmx5m -Xmx50m». Если я запустил приложение и нажимаю ссылку «Создать объект» примерно 5 раз, он попадет в ошибку OutOfMemory. Мониторинг памяти с помощью jConsole показывает, что потребление памяти растет примерно на 5 МБ каждый раз, и приложение никогда не отпускает эти 5 МБ.

Мои выводы до сих пор указывают на ERXObjectStoreCoordinatorSynchronizer в качестве виновника. В тестовом приложении Application.java включает синхронизацию. Конструктор Main.java просто выполняет фиктивный запрос, что в конечном итоге приводит к передаче Main._osc в ERXObjectStoreCoordinatorSynchronizer.addObjectStore() (синхронизатору требуется более 1 OSC для синхронизации чего-либо). Main.createDataStore() создает OSC и EC, добавляет объект DataStore в БД, затем уничтожает OSC и EC.

ПОСЛЕ того, как новый объект, OSC и EC сбрасываются, удаляются и выходят из сферы действия, синхронизатор запускается и добавляет этот вновь созданный (но теперь устаревший) объект к этому другому OSC, добавляет новый объект в базу данных EOD._snapshots array, где он остается до тех пор, пока не останется другой OSC.

Это кажется странным, что новый EO синхронизируется с другим OSC после его, и это ЕС и OSC, мертв, и пропал, и из области видимости. Не следует ли синхронизировать синхронизацию того факта, что EO выходит за пределы области действия и удаляет ее из всех остальных OSC (или не добавляет ли она других OSCs в первую очередь)?

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

ERXObjectStoreCoordinatorSynchronizer.synchronizer() setDefaultSettings (новые SynchronizerSettings (ложь, ложь, ложь, ложь)).

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

Является ли это ошибка, или я делаю что-то неправильно? Я смущен, почему другие люди, похоже, не сталкиваются с этим ... или, может быть, они сталкиваются с этим, но не заметили утечку памяти, потому что они не используют большие ОР (?)

ответ

1

Лучшее решение я нашел или избежать ERXObjectStoreCoordinatorSynchronizer (что означает, что вы также должны избегать ERXObjectStoreCoordinatorPool, так что использует синхронизатор), или отключить синхронизатор следующим образом:

ERXObjectStoreCoordinatorSynchronizer.synchronizer() .setDefaultSettings (новые параметры SynchronizerSettings (false, false, false, false));

Или вы могли бы, вероятно, уйти только с отключением InsertSnapshotProcessor:.

ERXObjectStoreCoordinatorSynchronizer.synchronizer() setDefaultSettings (новые SynchronizerSettings (ложные, истинные, истинные, true));

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

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

0

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

Стоит еще раз проверить следующее: ссылки на ЭО, EC, объект NSData, компоненты и посмотреть, случайно ли где-нибудь ваши огромные объекты и, что более важно, EC не пускается в GC-ed.

Возможно, нам понадобится дополнительная информация, которая поможет вам отладить эту проблему, если проблема не устранена!

+0

Спасибо за ответ! Я был немного удивлен, чтобы получить ответ на вопрос в WebObject связанного здесь. – Troy

+0

Я отредактировал мое сообщение выше с некоторыми подробностями моего теста. Проблема может быть в моем коде, но я не вижу, где это может быть ... – Troy

+0

Я пересмотрел свой первоначальный вопрос, чтобы добавить немного больше объяснений и ссылку в тестовое приложение, которое дублирует проблему, которую я видел. Надеюсь, это поможет указать мою ошибку (или ошибку проекта Wonder). – Troy

0

Извините, что разместил это как ответ, но я новичок в StackOverflow и не имею достаточного количества баллов для добавления комментария.Просто хотел добавить ссылку на проблему в репозитории Wonder Github, которая решает эту проблему, в надежде, что это поможет привести к решению:

https://github.com/wocommunity/wonder/issues/130 - от пользователя 'nullterminated' (я считаю, это Ramsey Gurley, который подтвердил этот вопрос - см. http://comments.gmane.org/gmane.comp.web.webobjects.wonder-disc/19078)

«Вероятно, ERXObjectStoreCoordinatorPool просачивается объектов EODatabase._DatabaseRecord всякий раз, когда размер пула> 1 и ОР сохраняются После многих часов в отладчике, я думаю, я понимаю почему ... "

«Обычно, когда EC сохраняет изменения, обнуляется уведомление ObjectsChangedInStore , моментальный снимок вставляется с _fastHashInsert EODatabase, а затем EC восстанавливает EO при обработке изменений (обновлений) или освобождает моментальный снимок при завершении (вставках). Эти действия огня соответствующий _fastHashRemove освободить снимок. «

» Проблема, как представляется, что ERXObjectStoreCoordinatorSynchronizer ретранслирует уведомление ObjectChangedInStore с другими ОГО в бассейне. Это приводит к снимкам вставленных, но не ЕС вокруг не убирать, снимки никогда не будут удалены.»