文件集用完了/没有释放内存的Ant XSLT任务

| 我有一个很大的(1.9 GB)XML文件,每个月都有要插入到MySQL数据库中的数据。我为此做了一个Ant脚本。 Ant XSLT任务无法处理这么大的文件,因此我有一个任务使用xml_split(来自xml-twig-tools)将1.9 GB的xml文件拆分为大约4 MB的较小的xml文件。 一切顺利。 我使用以下Ant XML来对所有这些XML文件运行XSLT任务:
    <target name=\"xsltransform\" depends=\"split\" description=\"Transform XML to SQL...\">
            <xslt basedir=\"${import.dir}/\" 
                  destdir=\"${import.dir}/sql/\"
                  style=\"${xsl.filename}\" force=\"true\">
                    <mapper type=\"glob\" from=\"*.xml\" to=\"*.sql\" />
                    <factory name=\"net.sf.saxon.TransformerFactoryImpl\"/>
            </xslt>
    </target>
问题是,一旦它在第一个XML文件上启动,我就会看到Linux顶部的\'RES \'内存随着每个下一个XML文件的增长而增加。由于它正在处理多个(不相关的)xml文件,因此我怀疑它会在每个xml文件的转换之间释放内存。好吧,它不会...在200个4MB的xml文件之后,java抛出了内存不足的异常:
BUILD FAILED
/var/lib/hudson/jobs/EPDB_Rebuild_Monthly/workspace/trunk/buildfiles/buildMonthly.xml:67: java.lang.OutOfMemoryError: Java heap space
at net.sf.saxon.tinytree.TinyTree.ensureNodeCapacity(Unknown Source)
at net.sf.saxon.tinytree.TinyTree.addNode(Unknown Source)
at net.sf.saxon.tinytree.TinyBuilder.startElement(Unknown Source)
at net.sf.saxon.event.Stripper.startElement(Unknown Source)
at net.sf.saxon.event.ReceivingContentHandler.startElement(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at net.sf.saxon.event.Sender.sendSAXSource(Unknown Source)
at net.sf.saxon.event.Sender.send(Unknown Source)
at net.sf.saxon.event.Sender.send(Unknown Source)
at net.sf.saxon.Controller.transform(Unknown Source)
at org.apache.tools.ant.taskdefs.optional.TraXLiaison.transform(TraXLiaison.java:194)
at org.apache.tools.ant.taskdefs.XSLTProcess.process(XSLTProcess.java:812)
at org.apache.tools.ant.taskdefs.XSLTProcess.execute(XSLTProcess.java:408)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:390)
at org.apache.tools.ant.Target.performTasks(Target.java:411)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1360)
at org.apache.tools.ant.Project.executeTarget(Project.java:1329)
我可以做些什么来防止XSLT任务耗尽我的全部内存吗? 还是应该重新考虑我的方法?     
已邀请:
我们都会同意,它应该释放内存,但是由于它不这样做,您可以尝试分拆
xslt
任务以分开通话。例如,使用Ant Contrib的
for
任务
<for param=\"file\">
    <fileset dir=\"${import.dir}\"/>
    <sequential>
        <xslt in=\"@{file}\"
              destdir=\"${import.dir}/sql/\"
              style=\"${xsl.filename}\" force=\"true\">
                <mapper type=\"glob\" from=\"*.xml\" to=\"*.sql\" />
                <factory name=\"net.sf.saxon.TransformerFactoryImpl\"/>
        </xslt>
    </sequential>
</for>
如果那不能解决问题,那么由于您正在使用Saxon,因此可以直接在派生的JVM中调用Saxon \的java类。例如。,
<java classname=\"net.sf.saxon.Transform\" failonerror=\"true\" fork=\"true\">
                <arg value=\"-s:${import.dir}\" />
                <arg value=\"-xsl:${xsl.filename}\" />
                <arg value=\"-o:${import.dir}/sql\" />
</java>
或者您可以同时尝试
<for param=\"file\">
    <fileset dir=\"${import.dir}\"/>
    <sequential>
        <basename property=\"@{file}.base\" file=\"@{file}\" suffix=\"xml\"/>
        <java classname=\"net.sf.saxon.Transform\" failonerror=\"true\" fork=\"true\">
                <arg value=\"-s:@{file}\" />
                <arg value=\"-xsl:${xsl.filename}\" />
                <arg value=\"-o:${import.dir}/sql/${@{file}.base}.sql\" />
        </java>
    </sequential>
</for>
为了获得加分,您可以尝试通过并行执行来加快速度。
<for param=\"file\">
    <fileset dir=\"${import.dir}\"/>
    <parallel>
        <basename property=\"@{file}.base\" file=\"@{file}\" suffix=\"xml\"/>
        <java classname=\"net.sf.saxon.Transform\" failonerror=\"true\" fork=\"true\">
                <arg value=\"-s:@{file}\" />
                <arg value=\"-xsl:${xsl.filename}\" />
                <arg value=\"-o:${import.dir}/sql/${@{file}.base}.sql\" />
        </java>
    </parallel>
</for>
    

要回复问题请先登录注册