![](/img/trans.png)
[英]Out of memory error : StringBuilder.append throwing OutOfMemoryError
[英]Base64 value causing StringBuilder.append out of memory error in SAX parser
我正在使用 SAX 解析器来解析 XML 文件,该文件是来自客户端服务器的响应。 标签包含在文件(jpg、png、pdf 等)的 Base64 解码值中。 其中一些我可以轻松地写入文件,但其中一些(我猜是大的)我在 StringBuilder.append 期间在 DefaultHandler 的覆盖方法上遇到了问题:
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (valueActive) { // set to true only when <value> tag is active
stringBuilder.append(ch, start, length); // OUT OF MEMORY error
}
}
在接下来的步骤中,我使用 Base64Encoder 编写文件:
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equalsIgnoreCase("value")) {
valueActive = false;
try (OutputStream stream = new FileOutputStream(my file here)) {
base64 = Base64.getDecoder().decode(stringBuilder.toString());
stream.write(base64);
} catch .... / omitted part of code
}
谁能建议如何解决内存不足问题? 堆栈跟踪:
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:596)
at java.lang.StringBuilder.append(StringBuilder.java:190)
at com....AttachmentHandler.characters(AttachmentHandler.java:47)
编辑:
Base64 来自 XML:
<value> String encoded with base64 </value>
对于 SAX 解析器,我使用的是 RestTemplate:
@Override
@Retryable
public Application performMultimediaRequest(String url) {
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
try {
SAXParser saxParser = saxParserFactory.newSAXParser();
restTemplate.execute(url,
HttpMethod.GET,
null,
responseExtractor -> {
try {
saxParser.parse(responseExtractor.getBody(), attachmentHandler);
} catch (SAXException e) {
log.error("Cannot parse API response with SAX parser");
}
return null;
}
);
} catch (SAXException | ParserConfigurationException e) {
log.error("Cannot parse response with SAX parser");
}
return attachmentHandler.getApplication();
}
要么增加 JVM 堆内存以满足StringBuilder
内存要求,要么使用Base64.getDecorder().wrap(InputStream)
方法:
返回用于解码 Base64 编码字节流的输入流。
返回的 InputStream 的 read 方法在读取无法解码的字节时会抛出 IOException。
关闭返回的输入流将关闭底层输入流。
您的示例代码的问题在于它不完整,我们不知道您从哪里获得char
值。 如果您从InputStream
获取char
值,您就可以完成wrap()
。
您可以希望通过从Base64.getDecorder().decode(String)
切换到Base64.getDecorder().decode(byte[])
来降低整体内存需求,但是如果您想节省堆内存,您应该将代码重写为使用InputStream
并且不要创建临时String
或byte[]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.