OutOfMemoryError:使用XSLT转换的Java堆空间
我想使用OutOfMemoryError:使用XSLT转换的Java堆空间,java,xml,xslt,Java,Xml,Xslt,我想使用XSLT转换XML文件。 我提出: 哪个输入文件有大约10000000行,我有错误: Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.sun.org.apache.xml.internal.utils.FastStringBuffer.append(FastStringBuffer.java:682) at com.sun.org.apache.xml.internal.dtm.r
XSLT
转换XML
文件。
我提出:
哪个输入文件有大约10000000行,我有错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.sun.org.apache.xml.internal.utils.FastStringBuffer.append(FastStringBuffer.java:682)
at com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM.characters(SAX2DTM.java:2111)
at com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.characters(SAXImpl.java:863)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.characters(AbstractSAXParser.java:546)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:455)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.getDTM(XSLTCDTMManager.java:421)
at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.getDTM(XSLTCDTMManager.java:215)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.getDOM(TransformerImpl.java:556)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:739)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351)
at ru.magnit.task.utils.AbstractXmlUtil.transformXML(AbstractXmlUtil.java:66)
at ru.magnit.task.EntryPoint.main(EntryPoint.java:72)
在这方面:
transformer.transform(text, new StreamResult(new File(getOutputFileName())));
原因是什么?在不考虑堆大小的情况下,是否可以以某种方式对其进行优化
更新:
我的XSLT
文件:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="entries">
<entries>
<xsl:apply-templates/>
</entries>
</xsl:template>
<xsl:template match="entry">
<entry>
<xsl:attribute name="field">
<xsl:apply-templates select="*"/>
</xsl:attribute>
</entry>
</xsl:template>
一般来说,XSLT 1.0和2.0使用的数据模型将完整的XML输入拉入树模型,以允许完整的XPath导航,从而导致内存使用量随着输入文档的大小而增加 因此,除非在当前文档大小导致内存不足的情况下增加堆空间,否则您无能为力,至少在一般情况下,可能会根据具体的XSLT代码进行特定于XSLT处理器和某些特定于XSLT的优化,但您无法避免处理器首先提取完整的文档。我们需要查看您的XSLT,以确定是否可以对其进行优化。分析样式表有助于确定需要优化的领域,我不确定Xalan是否支持这一点。我不确定堆栈跟踪是否仅仅意味着Xalan在为大型输入构建DTM(其树模型)时已经耗尽了内存,在这种情况下,优化XSLT代码显然没有帮助,因为它甚至没有执行 您可以尝试的一种特定于Java的方法是使用样式表创建SAX过滤器,并将其与默认转换器链接,以序列化过滤器的结果。我想我曾经尝试过这种方法,并发现它可以比使用转换器的传统方法消耗更少的内存 XSLT3.0试图用流()的新方法来解决内存问题,但是到目前为止,只有一个商业产品Saxon 9 EE的实现。通常,样式表不一定是可流化的,相反,您必须重写它以使其可流化(如果可能的话,例如,流式处理不可能对输入节点进行排序) 例如,您发布的样式表转换为XSLT 3.0以使用流(无需重写,只需将默认模式设置为可流)是
Saxon 9.8 EE和Exselt的beta版将其评估为可流化的。一般来说,XSLT 1.0和2.0使用数据模型,将完整的XML输入拉入树模型,以允许完整的XPath导航,从而导致内存使用量随着输入文档的大小而增加 因此,除非在当前文档大小导致内存不足的情况下增加堆空间,否则您无能为力,至少在一般情况下,可能会根据具体的XSLT代码进行特定于XSLT处理器和某些特定于XSLT的优化,但您无法避免处理器首先提取完整的文档。我们需要查看您的XSLT,以确定是否可以对其进行优化。分析样式表有助于确定需要优化的领域,我不确定Xalan是否支持这一点。我不确定堆栈跟踪是否仅仅意味着Xalan在为大型输入构建DTM(其树模型)时已经耗尽了内存,在这种情况下,优化XSLT代码显然没有帮助,因为它甚至没有执行 您可以尝试的一种特定于Java的方法是使用样式表创建SAX过滤器,并将其与默认转换器链接,以序列化过滤器的结果。我想我曾经尝试过这种方法,并发现它可以比使用转换器的传统方法消耗更少的内存 XSLT3.0试图用流()的新方法来解决内存问题,但是到目前为止,只有一个商业产品Saxon 9 EE的实现。通常,样式表不一定是可流化的,相反,您必须重写它以使其可流化(如果可能的话,例如,流式处理不可能对输入节点进行排序) 例如,您发布的样式表转换为XSLT 3.0以使用流(无需重写,只需将默认模式设置为可流)是
Saxon 9.8 EE和Exselt的beta版评估为可流化。我添加了我的
XSLT
文件,请参见另一个例子,为了使此功能在Saxon EE中发挥作用,您需要对Java代码做一些细微的更改,以确保您使用的TransformerFactory是Saxon的StreamableTransformerFactory
类的一个实例,请参见另一个例子,要使此功能在Saxon EE中发挥作用,您需要对Java代码进行轻微更改,以确保您使用的TransformerFactory是Saxon的StreamableTransformerFactory
类的实例。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="entries">
<entries>
<xsl:apply-templates/>
</entries>
</xsl:template>
<xsl:template match="entry">
<entry>
<xsl:attribute name="field">
<xsl:apply-templates select="*"/>
</xsl:attribute>
</entry>
</xsl:template>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:mode streamable="yes"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="entries">
<entries>
<xsl:apply-templates/>
</entries>
</xsl:template>
<xsl:template match="entry">
<entry>
<xsl:attribute name="field">
<xsl:apply-templates select="*"/>
</xsl:attribute>
</entry>
</xsl:template>
</xsl:stylesheet>