3

我构建了我的第一个 Java 程序,它建立在Interactive Brokers Java API之上。这可能很重要,也可能不重要。我只是用几个新类扩展了主要的 API 类。

该程序正在对远程服务器进行数据查询。当服务器响应时,我将接收到的数据记录到本地 MySQL 数据库中。一旦程序完成记录数据,程序将发出下一个数据请求。

在发出几百个服务器请求后,让程序运行一段时间后,我遇到了问题。我会看到这个错误,然后程序不会继续执行:

java.lang.OutOfMemoryError: Java heap space

我做了一些研究,根据我读到的内容,我得出结论,该程序正在创建许多新变量,而不是破坏旧的无价值变量。由于我使用 Netbeans 进行开发,因此我使用Netbeans 分析器检查是否是这种情况。看这里的图片:

在此处输入图像描述

运行程序一段时间后,越来越多的内存被Byte. 所以看来我的理论还是正确的。

我真的不知道从这里去哪里。没有对类或特定变量的引用,只是变量类型。如何确定问题出在哪里?

更新

我更正了 BigMike 在评论中提到的一个特定问题。以前,我在 JDBC MySQL 连接器 API 中创建了许多语句,并且我正在调用.execute()以执行这些语句,但我没有使用.close().

我确保statement.close()在每次执行后添加调用,并且程序现在运行得更好。通过查看该程序的 RAM 使用情况,它似乎解决了这个问题。我也没有看到Java heap space错误了,这很好。

谢谢!

4

2 回答 2

2

仅凭这一点很难说可能出了什么问题。

它可能与您正在打开的 Streams 在您不再需要它们时没有关闭它们有关。仔细检查分配资源的方法(从文件、数据库等读取),尤其是当它们将数据读入流时,并确保在 finally 子句中关闭这些流。

除此之外,您可以尝试分析更频繁地调用哪些方法等,以尝试将问题缩小到代码的特定部分。

我找到了一个网站,它对垃圾收集的工作原理以及可能导致 OutOfMemoryErrors 的原因进行了合理的解释:

http://www.kdgregory.com/index.php?page=java.outOfMemory

如果你通读了那篇文章,有一个对 Object[] 和 byte[] 的高分配的具体参考,这可能会为你指明正确的方向。

于 2013-03-14T15:36:06.057 回答
1

一般来说,这是由于以下两个原因之一:

  1. 应用程序中存在内存泄漏,导致应用程序无法释放项目进行垃圾回收,从而导致 JVM 随着时间的推移耗尽内存。

  2. 应用程序尝试了一次性操作,该操作需要比可用内存更多的内存,导致 JVM 由于该操作而耗尽内存。

由于您的输出似乎表明大部分内存被一百万个小字节数组消耗,我猜#1可能是罪魁祸首;但是,要验证这一点,请重新启动您的应用程序并观察它随着时间的推移的内存消耗。它会上下反弹,但实际上你只需要观察消费趋势。如果消耗平均值随着时间的推移继续攀升,则说明存在内存泄漏。

要解决此问题,您通常需要源代码,并且需要找到代码中创建、使用和“存储”问题对象的部分,这些部分远远超出了上次使用它们的时间。解决方案是更正代码以不再存储它们。HashMaps、Lists 和其他 Collections 往往是内存泄漏问题的帮凶。

如果您缺少源代码,您可以尝试测量内存消耗的趋势,并安排应用程序的关闭和重新启动以有效地“重置时钟”,这样您就可以选择停机时间,而不是看着应用程序为您选择它。

如果它是一次性操作(不太可能考虑您的数据),那么在触发事件发生之前,您不会看到内存消耗的上升趋势。在这种情况下,通过访问源代码,您应该保护您的应用程序免受处理远远超出正常操作参数的数据。例如,从网络读取一条消息通常只需要几 KB,但在特殊情况下,客户端可能会永远传输。在这种情况下,如果超过 10 MB 的最大消息大小限制,请终止消息处理并将消息丢弃并报错。

在后一种情况下,如果无法访问源代码,唯一的希望是识别传入的干扰,寻找错误传输的来源,并尝试对其进行操作以防止输出过载。

如何处理这些技术的变化是巨大的,但现在你有一些想法。

于 2013-03-14T16:53:34.693 回答