Ошибка OutOfMemoryError: Java heap space при использовании JSoup. Сохранение большого HTML документа

459
24 июня 2017, 10:46

Использую библиотеку Jsoup для работы с HTML документами. Загружаю из шаблона HTML документ,

File input = new File(context.getRealPath("/sides_to_doc_template.html"));
org.jsoup.nodes.Document document = Jsoup.parse(input, "UTF-8");

добавляю в него много (очень много) строк. В том числе и картинок.

BASE64Encoder encoder = new BASE64Encoder();
document.getElementById("472")
        .attr("src", "data:image/png;base64," + encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/472.png")))));
for (Map<String, Object> stringObjectMap : sidesToPDF) {
    Element not_one = document.getElementById("one").clone();
    Elements itemElements = not_one.select(".item-value");
    for (Element itemElement : itemElements) {
        String className = itemElement.className().replace("item-value ", "");
        Object o = stringObjectMap.get(className);
        if (o != null) itemElement.text(o.toString());
    }

    Element img;
    String dataURL;
    Object image = stringObjectMap.get("img_side");
    img = not_one.select(".side_img").first();
    dataURL = image != null ?
            encoder.encode((byte[]) image) :
            encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/12.png"))));
    img.attr("src", "data:image/png;base64," + dataURL);

    image = stringObjectMap.get("img_map");
    img = not_one.select(".map_piece_img").first();
    dataURL = image != null ?
            encoder.encode((byte[]) image) :
            encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/22.png"))));
    img.attr("src", "data:image/png;base64," + dataURL);
    document.getElementsByTag("body").get(0).appendChild(not_one);

Потом при вызове метода document.html()

FileOutputStream out = new 
FileOutputStream(context.getRealPath("/test.html"));
out.write(document.html().getBytes("UTF-8"));
out.close();

вываливается ошибка

Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332) ~[na:1.8.0_51]
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137) ~[na:1.8.0_51]
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121) ~[na:1.8.0_51]
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:622) ~[na:1.8.0_51]
at java.lang.StringBuilder.append(StringBuilder.java:202) ~[na:1.8.0_51]
at java.lang.StringBuilder.append(StringBuilder.java:76) ~[na:1.8.0_51]
at org.jsoup.nodes.Entities.escape(Entities.java:217) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Attribute.html(Attribute.java:94) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Attributes.html(Attributes.java:234) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Element.outerHtmlHead(Element.java:1262) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Node$OuterHtmlVisitor.head(Node.java:709) ~[jsoup-1.10.3.jar:na]
at org.jsoup.select.NodeTraversor.traverse(NodeTraversor.java:31) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Node.outerHtml(Node.java:581) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Element.html(Element.java:1300) ~[jsoup-1.10.3.jar:na]
at org.jsoup.nodes.Element.html(Element.java:1294) ~[jsoup-1.10.3.jar:na]
at uz.dd.controller.doc_servlet.DocServletController.exportSidesToWord(DocServletController.java:941) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_51]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_51]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_51]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_51]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE]

Я понимаю, документ большой, да что там - большой? Он огромный. В коллекции sidesToPDF содержатся больше 500 строк, и в каждой строке (Map stringObjectMap) есть по две картинки, которые нужно как-то вставить в HTML документ. Когда строк 87 - то все работает, но итоговый HTML документ, записанные в FileOutputStream out весит 65 МБ. В том методе document.html() видимо идет работа со строками, но я не знаю как мне еще сохранить такой документ?

ПОлный код метода (Используется Spring Framework)

@RequestMapping("/exportSidesToWord")
public void exportSidesToWord(HttpServletRequest request, HttpServletResponse response,
                             /* @RequestParam("constrIds[]")*/ Integer[] constrIds,
                             /* @RequestParam("sideIds[]") */Integer[] sideIds,
                              Integer nores) throws IOException, InvalidFormatException, SQLException, DocumentException {
    ArrayList<Map<String, Object>> sidesToPDF = service.constrSidesToPDF(constrIds, sideIds, nores);
    File input = new File(context.getRealPath(path_to_template_folder + "/sides_to_doc_template.html"));
    org.jsoup.nodes.Document document = Jsoup.parse(input, "UTF-8");
    BASE64Encoder encoder = new BASE64Encoder();
    document.getElementById("472")
            .attr("src", "data:image/png;base64," + encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/472.png")))));
    for (Map<String, Object> stringObjectMap : sidesToPDF) {
        Element not_one = document.getElementById("one").clone();
        Elements itemElements = not_one.select(".item-value");
        for (Element itemElement : itemElements) {
            String className = itemElement.className().replace("item-value ", "");
            Object o = stringObjectMap.get(className);
            if (o != null) itemElement.text(o.toString());
        }

        Element img;
        String dataURL;
        Object image = stringObjectMap.get("img_side");
        img = not_one.select(".side_img").first();
        dataURL = image != null ?
                encoder.encode((byte[]) image) :
                encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/12.png"))));
        img.attr("src", "data:image/png;base64," + dataURL);

        image = stringObjectMap.get("img_map");
        img = not_one.select(".map_piece_img").first();
        dataURL = image != null ?
                encoder.encode((byte[]) image) :
                encoder.encode(Files.readAllBytes(Paths.get(context.getRealPath(path_to_template_folder + "/22.png"))));
        img.attr("src", "data:image/png;base64," + dataURL);
        document.getElementsByTag("body").get(0).appendChild(not_one);
    }
    document.getElementById("one").remove();
    FileOutputStream out = new FileOutputStream(context.getRealPath(path_to_template_folder + "/test.html"));
    out.write(document.html().getBytes("UTF-8"));
    out.close();

}

Вот содержание HTML шаблона, кому интересно:

<body>
<div id="one">
    <div class="container">
        <div class=" inline-div col-75 ">
            <div class="img-container">
                <img class="side_img" src="1.png"><br>
                <img class="map_piece_img" src="2.png">
            </div>
        </div>
        <div class="inline-div col-25">
            <div class="detail-item">
                Тип конструкции
                <div class="item-value constr_type">
                    Призматрон
                </div>
            </div>
            <div class="detail-item">
                Размер конструкции
                <div class="item-value constr_size">
                    3х9 м
                </div>
            </div>
            <div class="detail-item">
                Зона
                <div class="item-value circus">
                    1
                </div>
            </div>
            <div class="detail-item">
                Адрес размещения
                <div class="item-value adresse">
                    Угол Шахризабской и Тараккиет
                </div>
            </div>
            <div class="detail-item">
                Описание
                <div class="item-value description">
                    Напротив роддома
                </div>
            </div>
            <div class="detail-item">
                Код конструкции
                <div class="item-value nummer_side">
                    472
                </div>
            </div>
            <div class="detail-item">
                Стоимость
                <div class="item-value kost">
                    1300 000 сум
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <img id="472" src="472.png" style="margin-top: 35px;  width: 100%;">
    </div>
</div>
</body>
READ ALSO
не пойму, в чем ошибка [требует правки]

не пойму, в чем ошибка [требует правки]

The character encoding was not declaredProceeding using windows-1252

514
Как заблокировать доступ к изображению?

Как заблокировать доступ к изображению?

Чтоб при просмотре страницы картинка отображалась, а при переходе или скачивании было 403

337
Помогите с версткой на Bootstrap 3

Помогите с версткой на Bootstrap 3

Добрый деньПодскажите, как сверстать такой дизайн, с использованием bootstrap

308
Почему не работает margin:auto 0 у слайдера?

Почему не работает margin:auto 0 у слайдера?

Недавно версткой стал заниматься, возникла проблема при вертикальном выравнивании

411