【问题标题】:Memory build up in a java program GapContent$MarkData在 Java 程序 GapContent$MarkData 中建立内存
【发布时间】:2013-05-22 05:25:31
【问题描述】:

我目前正在开发一个应用程序,它需要大约每 20 毫秒快速执行一次(是的,我知道,一开始就不应该使用 Java)。我做了很多优化代码的工作,所以它不会太计算贪婪。但是,正如我所见,我可能没有在 GUI 和内存优化方面付出足够的努力。我的应用程序可以以我想要的速度运行,但在 1-2 分钟后它会急剧变慢,这表明存在内存问题。

我确实在 NetBeans 下运行了分析器,发现大部分内存都被 javax.swing.text.GapContent$MarkData 占用了

然后在谷歌上搜索,我发现几乎没有什么可以帮助我解决这个问题。那么有没有人可以帮助我?我的第一个猜测是垃圾收集器运行的时间不够长,无法擦除未使用的对象……但我没有比这更多的线索。

【问题讨论】:

  • 为了获得帮助,您必须添加一些代码..
  • 好吧,实际上有成千上万行代码。我想知道从哪里开始。
  • Swing 因所有这些内存堆积而臭名昭著(我不会称之为内存泄漏)。最好重用 Swing 元素,而不是每次都重新实例化它们。
  • +1 代表profiling;现在使用Profile > Profile Project > CPU 查找和定位热点。
  • @trashgod 该死,无法相信,速度变慢是由于每次迭代都会关闭并打开与数据库的连接(通过 Wi-Fi 连接)的函数。很高兴现在存在这样的工具......如果没有,我肯定不会发现问题。

标签: java swing memory


【解决方案1】:

您有权使用profiling;现在使用Profile > Profile Project > CPU 查找和定位热点。

速度变慢是由于每次迭代时关闭并打开与数据库的连接的函数。

考虑使用SwingWorker在后台查询数据库,process()结果在event dispatch thread上,如相关example所示。

【讨论】:

  • +1 有两个很棒的建议。在后台点击数据库是正确的,并且会使应用程序感觉更快,但实际上不会提高吞吐量。 Publish/Process 也让它感觉更快,并且它确实允许一些并发:一个线程可以对一些结果进行 ui 工作,而其余的正在被发现/生成。但最大的改进将来自解决底层问题 - 编写批处理操作,以便每次迭代时不会打开和关闭 db 连接。
【解决方案2】:

您所说的“内存积累”只有 600Kb。如果这 600Kb 有问题,我会质疑您对 Java 和 Swing 的选择。

我有一个应用程序有时会生成数百兆字节的日志消息。 我猜你的 GUI 应用程序有点相似。该应用程序可能有一个显示日志的 JTextPane。当应用程序运行时,它会将消息添加到 JTextPane。
JTextPane 使用的 Document 实现是 PlainDocument
即使您可能总是只在顶部或底部插入新的日志消息,PlainDocument 实现是通用的。它通过在底层文本流中放置一个间隙然后将更改放入间隙中来支持在文档中的任何位置进行修改。当应用程序将新消息插入到文档中时,它会产生很多间隙。
要显示的实际文本必须存在于某处。可能有更好的方法来实现一个巨大的文本窗格,但默认的 JTextPane 在探查器看来就像内存泄漏。如果您有 600kb 的日志消息,那么它至少会占用 600kb 的内存。

【讨论】:

  • +1 感谢您向我指出这一点(我被我的确定性蒙蔽了双眼)。也许我的应用程序性能下降是由于其他原因。我将尝试让应用程序在没有 GUI 的情况下运行,以查看问题是否仍然存在并寻找可能导致此问题的潜在组件。
【解决方案3】:

您应该知道Java 控制台使用PlainDocumentGapContent$MarkData,并且只要打开控制台并在其中包含大量数据就会导致出现这种“内存泄漏”。清除控制台以查看MarkData 的数量回落到可接受的水平。

【讨论】:

  • +1 与问题无关,因为问题最终不是内存泄漏,而是有趣的信息。
猜你喜欢
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多