我需要SAX解析,因为我想检查恶意格式错误的XML。这是我第一次使用这个库。
我创建了一个XML文件(18MB),其中包含一个名字非常长的属性。
<?xml version="1.0"?>
<company>
<staff>
<firstname VERYLONGATTRIBUTENAME...VERYLONGATTRIBUTENAME="some value">
yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff>
<firstname>low</firstname>
<lastname>yin fong</lastname>
<nickname>fong fong</nickname>
<salary>200000</salary>
</staff>
</company>
我只是像这样打电话给SAXParser
saxParser.parse("test.xml", handler);
所有事件处理程序都是空的。但是发生 OutOfMemoryError:Java堆空间。 为什么会这样?我选择SAX是因为它是基于流/事件的,并且在处理这类问题时没有问题(与DOM相比)。
编辑:我通过每次加倍来增加属性名称的长度。它一直有效,直到我达到这个18MB的文件。编辑2:堆栈跟踪
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.StringValue.from(StringValue.java:24)
at java.lang.String.<init>(String.java:178)
at com.sun.org.apache.xerces.internal.util.SymbolTable$Entry.<init>(SymbolTable.java:338)
at com.sun.org.apache.xerces.internal.util.SymbolTable.addSymbol(SymbolTable.java:178)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.scanName(XMLEntityScanner.java:726)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanAttribute(XMLDocumentFragmentScannerImpl.java:1523)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1320)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2756)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:277)
at com.thundercloud.httpfilter.XMLParser.test(XMLParser.java:150)
at com.thundercloud.httpfilter.HTTPInterceptor.main(HTTPInterceptor.java:34)
提前致谢
答案 0 :(得分:1)
您可以在Eclipse Run-&gt; Run Configuration中找到您的内存设置。查找Java应用程序并找到您尝试运行的类的名称,选择它,单击Arguments选项卡。 VM Arguments部分的设置是什么?如果为空,请将以下值添加到VM Arguments部分。
-Xms512M -Xmx1024M
此外,还有一个与JDK6有关SAX parser throws OutOfMemoryError的错误。受影响的版本在更新14之前是JDK6。请检查您的Java版本以确保它不适用于您。
根据评论编辑,我修改了我的答案并建议在VM参数部分添加以下VM设置
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="c:\temp\oomdump.hprof"
。
然后你可以使用像Eclipse MAT http://www.eclipse.org/mat/这样的工具来分析转储文件,看看究竟是什么问题
答案 1 :(得分:0)
首先,我认为任何属性名称都不会那么长。 尝试增加堆大小,然后检查。
java -jar -Xms<min_size> -Xmx<max_size> <ur_jar>
答案 2 :(得分:0)
您可能想要查看ScaleDOM,它允许解析非常大的XML文件: https://github.com/whummer/scaleDOM
由于XML节点的延迟加载,ScaleDOM的内存占用量很小。它只将XML文档的一部分保留在内存中,并在必要时从源文件重新加载节点。