Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OutOfMemoryError:使用XSLT转换的Java堆空间_Java_Xml_Xslt - Fatal编程技术网

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>