簡體   English   中英

Base64 值導致 SAX 解析器中的 StringBuilder.append 內存不足錯誤

[英]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並且不要創建臨時Stringbyte[]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM