Xalan XSLT - 内存堆空间不足

Posted

技术标签:

【中文标题】Xalan XSLT - 内存堆空间不足【英文标题】:Xalan XSLT - Out of Memory Heap Space 【发布时间】:2012-02-22 17:00:37 【问题描述】:

我的项目有一个报告模块,它以 XML 的形式从数据库收集数据并在其上运行 XSLT 以生成用户所需的报告格式。此时的选项是 html 和 CSV。

我们使用 Java 和 Xalan 与数据进行所有交互。

不好的部分是用户可以请求的这些报告之一是 143MB(大约 430,000 条记录),仅用于 XML 部分。当它被转换成 HTML 时,我用完了堆空间,最多为堆保留 4096G。这是不可接受的。

似乎问题只是数据太多,但我不禁想到有一个更好的方法来处理这个问题,而不是限制客户并且无法满足功能需求。

我很高兴根据需要提供更多信息,但我不能透露太多有关该项目的信息,因为我相信你们中的大多数人都理解。此外,答案是肯定的;我同时需要所有数据:我无法对其进行分页。

谢谢

编辑

我使用的所有转换类都在 javax.xml.transform 包中。实现如下所示:

final Transformer transformer = 
  TransformerFactory.newInstance().newTransformer(
    new StreamSource(new StringReader(xsl)));
final StringWriter outWriter = new StringWriter();
transformer.transform(
  new StreamSource(new StringReader(xml)), new StreamResult(outWriter));
return outWriter.toString();

如果可能的话,我想保留 XSLT 的原样。 StreamSource 的处理方法应该允许我在处理一些数据时对其进行 GC,但我不确定 XSLT(函数等)的哪些限制可能需要它进行适当的清理。如果有人可以向我指出详细说明这些限制的资源,那将非常有帮助。

【问题讨论】:

【参考方案1】:

我们可以通过做两件事来改善这一点。

    我们采用 XML 源和目标格式并将它们制作成临时文件。这将初始创建和存储保持在 RAM 之外,因为数据来自数据库并且也被写回 DB。只需一个数据句柄即可。

    使用Saxonica 转换器。这允许做一些事情,包括 SAX 样式的转换和 XSLT 2.0 的使用,而 Xalan 解析器不这样做。

【讨论】:

【参考方案2】:

XSLT 的问题在于,在进行转换时,您需要在内存中拥有整个源文档(以及结果文档)的 DOM 表示。对于大型 XML 文件,这是一个严重的问题。

您对允许流式转换的系统感兴趣,其中完整的文档不必在内存中重新存储。也许 STX 是一种选择: http://www.xml.com/pub/a/2003/02/26/stx.html http://stx.sourceforge.net/。它与 XSLT 非常相似,因此如果您的 XSLT 样式表以直接的方式应用于 XML,则将其重写为 STX 可能非常简单。

【讨论】:

此外,最新版本的 XSLT 确实包含流功能:w3.org/TR/xslt-21/#streaming-concepts。我自己没试过。 Saxon 也支持streaming,尽管您可以为此模式编写的 XSLT 更加有限。还有更多讨论here。 是的,这就是我所指的 XSLT 2.1 版本中的新增功能。限制表现力可能是使其成为流媒体的必要条件。 查看编辑。据我了解,我已经在使用 Xalan 的流媒体选项(StreamSourceStreamResult 来自 javax.xml.transform.stream 包)。感谢您的回复;我什至不确定有多少人在使用这些东西。 StreamSource 是一个糟糕的类名。之所以称为StreamSource,是因为它从InputStream 中读取数据,而不是因为SourceResult 之间发生的转换是流式转换。

以上是关于Xalan XSLT - 内存堆空间不足的主要内容,如果未能解决你的问题,请参考以下文章

理解 JVM 内存分配和 Java 内存不足:堆空间

内存不足:Java 堆空间,但在查看堆空间时最大使用 50 MB

内存不足错误,java堆空间

内存不足错误:Java 堆空间

Hive - 内存不足异常 - Java 堆空间

sparklyr中的堆空间不足,但有足够的内存