首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebObjects中的内存泄漏

WebObjects中的内存泄漏
EN

Stack Overflow用户
提问于 2012-04-24 17:31:00
回答 3查看 604关注 0票数 1

一段时间以来,我一直在与使用苹果EOF框架的问题作斗争。有时候,当创建EOEnterpriseObject或从DB将其拖到编辑上下文中时,EOF甚至在释放和删除相关的企业对象、编辑上下文和对象存储之后,也不会放弃对象所消耗的内存。大多数对象,它似乎,只是处理很好的EOF,但我有2个对象,EOF始终保持使用的内存对象,直到应用程序重新启动。这两个to都可能非常大(它们包含一个用于保存文件附件的NSData对象)。

使用JProfiler,我发现EODatabase._snapshots数组保存了对EOs问题的引用。

我想知道是否还有其他人在EOF和/或Wonder项目方面也有类似的问题。因为我一直在两种不同的场景下看到这个问题,所以我希望它是比较常见的,因此,我有一个解决方案。

我正在使用最新的WebObjects库(5.4.3)和最新的Wonder库。

下面的代码不是我的确切代码,但它是内存泄漏的最小的例子:

代码语言:javascript
复制
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 an,最终会遇到OutOfMemory错误。

2012-12-26编辑

我对此做了更多的调查。问题似乎出现在Project库中,而不是EOF库中。我理解“问题”可能是我和/或我的理解,而不是Wonder。:)

我创建了一个测试应用程序,它复制了我一直看到的问题,并将其发布在github:https://github.com/t-evans/memory-leak-test.git上。

测试应用程序通常只是Eclipse添加新的Wonder应用程序时创建的默认应用程序。这些更改是在Application.java中添加一行,Main.java中的大部分代码,当然还有模型文件。目前,它被配置为连接到一个名为"memleaktest“的postgres数据库。

我的应用程序的运行配置只有两个VM args:"-Xmx5m -Xmx50m“。如果我启动该应用程序并单击"Create“链接约5次,它将遇到一个OutOfMemory错误。使用jConsole监视内存显示,每次内存消耗增加约5MB,而应用程序从不放弃这5MB。

到目前为止,我的发现指出ERXObjectStoreCoordinatorSynchronizer是罪魁祸首。在测试应用程序中,Application.java打开同步。ERXObjectStoreCoordinatorSynchronizer.addObjectStore()的构造函数只执行一个虚拟查询,这最终导致Main._osc被传递给Main._osc(同步器需要超过一个OSC来同步任何东西)。Main.createDataStore()创建OSC和EC,向DB中添加一个DataStore对象,然后对OSC和EC进行核弹。

在新对象OSC和EC被核武器化、释放和超出作用域后,同步器运行并将新创建的(但现在已经过时)对象添加到另一个OSC中,后者最终将新对象重新添加到EODatabase._snapshots数组中,在该数组中,它一直保持到释放其他OSC为止。

奇怪的是,新的EO与它之后的其他OSC同步,而EC和OSC则死了,消失了,超出了范围。同步器是否也应该同步EO超出范围的事实,并将其从所有其他OSC中删除(或者不将其添加到其他OSC中)?

我知道同步可以通过调用

代码语言:javascript
复制
ERXObjectStoreCoordinatorSynchronizer.synchronizer().setDefaultSettings(
    new SynchronizerSettings(false, false, false, false));

这样可以避免这个问题,但是同步器的默认设置已经打开了,这会导致相当大的泄漏。

这是个错误,还是我做错了什么?我搞不懂为什么其他人不会遇到这种情况。或者他们正在遇到它,但是没有注意到内存泄漏,因为他们没有使用大型的EOs(?)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-31 19:00:47

我发现的最佳解决方案是要么避免ERXObjectStoreCoordinatorSynchronizer (这意味着您还需要避免ERXObjectStoreCoordinatorPool,因为它使用同步器),要么禁用同步器,如下所示:

ERXObjectStoreCoordinatorSynchronizer.synchronizer().setDefaultSettings(new

SynchronizerSettings(假,假);

或者,您可能只需禁用InsertSnapshotProcessor就可以了:

ERXObjectStoreCoordinatorSynchronizer.synchronizer().setDefaultSettings(new SynchronizerSettings(false,truetruetrue);

因为内存泄漏似乎就是在那里发生的(其他的可能也会导致问题,但我还没有具体看到)。

在发布到Project邮件组之后,似乎没有人有比上面更好的解决方案了。

票数 1
EN

Stack Overflow用户

发布于 2012-04-28 02:40:20

我希望您已经验证了代码的所有部分并对其进行了分析。但我仍然觉得问题只存在于您的代码中。

值得再次检查以下内容:对EOs、EC、NSData对象、组件的引用,并查看您的大型对象(更重要的是EC )是否被授予GC-ed。

如果问题仍然存在,我们可能需要一些更多的信息来帮助您调试这个问题!

票数 0
EN

Stack Overflow用户

发布于 2013-10-05 11:53:37

很抱歉将此作为回复发布,但我对StackOverflow并不熟悉,也没有足够的点来添加评论。我只想在Wonder Github存储库中添加一个解决这个问题的引用,希望它有助于找到解决方案:

https://github.com/wocommunity/wonder/issues/130 -从用户‘无空终止’(我相信这是Ramsey Gurley,谁证实了问题--见http://comments.gmane.org/gmane.comp.web.webobjects.wonder-disc/19078)

“看来,每当池大小>1时,ERXObjectStoreCoordinatorPool就会泄漏EODatabase._DatabaseRecord对象,并保存EOs。

“通常情况下,当EC保存更改时,触发ObjectsChangedInStore通知,用EODatabase的_fastHashInsert插入快照,然后EC在处理更改(更新)时重新错误EO,或在fire上释放快照(插入)。这些操作触发相应的_fastHashRemove以释放快照。”

“问题似乎是ERXObjectStoreCoordinatorSynchronizer将ObjectChangedInStore通知重新广播到池中的其他OSC。这会导致快照被插入,但是没有EC来清理,快照永远不会被删除。”。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10302982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档