【问题标题】:OutOfMemory when parsing String XML to Java Objects将字符串 XML 解析为 Java 对象时的 OutOfMemory
【发布时间】:2012-07-08 00:36:27
【问题描述】:

问题 - 解析 XML 字符串时,我的程序中的内存利用率一直在增长。

我有一个通过 TCP 端口实时传输的 XML 流。
我使用 Netty 提取 xml 数据,然后使用 XStream 将 XML 字符串反序列化/解组到 Java 对象树中。

当我使用 netbeans 配置文件监控内存消耗时,我看到 HEAP 随着时间的推移而增长,然后最终 JVM 抛出 OutOfMemory 异常。 我跟踪了调用堆栈,并附上了我正在运行的一个测试的屏幕截图。

当我将 XML 字符串反序列化/解组为 Java 对象时,似乎正在发生内存消耗。

我在 XStream 中尝试了不同的解析器来进行解析 - XPP3、KXML、STAX。我什至尝试过 JAXB 而不是 XStream 来解组。 无论我使用什么解析器,问题仍然存在。

到目前为止,我已经尝试了所有这些不同的解析器,但我遇到了同样的问题。

  xstream1 = new XStream(new KXml2Driver());
  xstream2 = new XStream(new StaxDriver());
  xstream3 = new XStream(new JDomDriver());
  xstream4 = new XStream(new Xpp3Driver());

就像我提到的,我什至尝试用 JAXB 解组而不是 XStream...仍然是同样的问题。

如果你看一下附加的图像,它的这个 Arrays.copyOfRange 调用就在显示的 char[] 下方.... 无论是哪个解析器,此调用始终显示在跟踪的顶部。

我完全不知道如何解决或解决这个问题

请注意 - 我不是从文件中读取 XML。我得到一个包含小 XML 块的实时数据流。我提取每个块以将其转换为 Java 对象以供进一步处理

谢谢 一个

【问题讨论】:

    标签: java parsing jaxb netty xstream


    【解决方案1】:

    嗯,根据您向我们展示的证据,最简单的解释是您的 JVM 堆太小。尝试按照manual entry 中所述为java 命令添加“-Xmx”选项。

    如果这不起作用,那么您需要更深入地了解您的应用程序在做什么:

    • 这些“小”XML 块的大小是否有上限?你能得到一个比你允许的更大的块吗?

    • 您的应用程序的处理是否将每个块中的内容保存在一个长期存在的内存数据结构中?你可以为该数据结构的大小设置一个上限吗?也许通过扔东西? (或者通过使用“弱引用”让 GC 将它们丢弃?)

    • 您的应用程序是否存在内存泄漏?

    【讨论】:

    • A) 没有上限 B) 我不会故意保留任何东西...除非有错误。 C)这就是我试图弄清楚的,事情只是在我提到的这个解析区域指出,内存似乎正在发生。
    • 如果你没有保留任何数据,那么很难看出你是如何泄漏内存的,在 XML 解析或其他方面。但无论哪种方式,都有办法追踪存储泄漏。例如:oracle.com/technetwork/java/javase/memleaks-137499.html#gbywf
    • 我的应用程序确实存在内存泄漏 - 修复后工作正常。
    【解决方案2】:

    上面的答案是可靠的。我只想补充一点,内存中的对象图可能很昂贵。如果我理解您的描述,您有一个包含许多小 XML 块的 XML 流? SAX 解析以及管道方法可能是您的答案。当 SAX 解析器找到每个工作块时,它会将其传递给下游进程,而无需将所有对象拉入内存。

    【讨论】:

    • 如果我们假设这些块确实很小并且有一个有界的大小,那么假设相应的 DOM 会很小(-ish)并且有界并不是一件容易的事。在这种情况下,转换为 SAX 解析器需要做很多工作……与仅增加堆大小相比。
    • 伙计们 - 正如我的帖子中提到的,我已经尝试过,STAX、XPP3、KXML2 和 JDOM ......都给了我同样的问题......我想相信它在我的自己的代码,但我在分析器中看到的堆栈跟踪指出了完全不同的地方。我很难将它映射回我自己的代码。我目前正在切换到使用另一种解决方案 - 放弃 XML,只是在我的客户端和服务器之间序列化/反序列化我的 Java 数据对象。如果这也给了我内存泄漏,那么我可以尝试在我自己的代码中跟踪内存泄漏
    • 我认为您可能误解了探查器的输出。解析器中发生分配失败的事实并不意味着解析器正在泄漏内存。
    猜你喜欢
    • 2012-05-17
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多