Java Aspose HTML to PDF issue with v25.1 (Heap space error)

I have an issue where the Aspose Java HTMLtoPDF functionality broke from v24.9 to v25.1.

The result of using 25.1 is that the JVM crashes with a JAVA heap space error:

> Task :RiskCommsModule:processTestResources NO-SOURCE
> Task :RiskCommsModule:testClasses
Connected to the target VM, address: 'localhost:42311', transport: 'socket'
HTML2PDF start...
12:29:40.658 [pool-3-thread-3] INFO com.psybergate.mmi.communications.module.utilities.HtmlToPdf -- Downloading file https://content.momentum.co.za/content/images/banner/SignatureAnnelineCross.png
12:29:40.676 [pool-3-thread-1] INFO com.psybergate.mmi.communications.module.utilities.HtmlToPdf -- Downloading file https://content.momentum.co.za/content/images/banner/ImportantNoticeBanner.png
12:29:40.681 [pool-3-thread-4] INFO com.psybergate.mmi.communications.module.utilities.HtmlToPdf -- Downloading file https://content.momentum.co.za/content/images/banner/MyriadOtpEmailFooter.png
12:29:40.692 [pool-3-thread-2] INFO com.psybergate.mmi.communications.module.utilities.HtmlToPdf -- Downloading file https://content.momentum.co.za/content/images/banner/DiscountGrid.png
> Task :RiskCommsModule:test
Disconnected from the target VM, address: 'localhost:42311', transport: 'socket'
> Task :RiskCommsModule:test FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':RiskCommsModule:test'.
**Caused by: java.lang.OutOfMemoryError: Java heap space**

HtmlToPDF.Java:

package com.psybergate.mmi.communications.module.utilities;

import com.aspose.pdf.*;
import com.aspose.pdf.facades.DocumentPrivilege;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

public class HtmlToPdf {

    private static final Logger log = LoggerFactory.getLogger(HtmlToPdf.class);

    public static byte[] downloadFile(String s)
    {
        log.info(String.format("Downloading file %s", s));
        try {
            URL url = new URL(s);
            URLConnection conn = url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.connect();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            IOUtils.copy(conn.getInputStream(), baos);
            baos.close();
            return baos.toByteArray();
        }
        catch (Exception e)
        {
            log.error(String.format("Exception(HtmlToPdf.downloadFile) %s", ExceptionUtils.getMessage(e)));
        }
        return new byte[0];
    }

    private static LoadOptions.ResourceLoadingResult customResourceLoader(String s)  {
        return new LoadOptions.ResourceLoadingResult(downloadFile(s));
    }

    public static byte[] convertHtmlToPdf(String html) throws IOException {
        if (!StringUtils.isEmpty(html)) {
            try {
                InputStream targetStream = new ByteArrayInputStream(html.getBytes());

                com.aspose.pdf.HtmlLoadOptions loadOptions = new com.aspose.pdf.HtmlLoadOptions();
                loadOptions.setHtmlMediaType(HtmlMediaType.Print);
                loadOptions.setEmbedFonts(true);
                loadOptions.setCustomLoaderOfExternalResources(HtmlToPdf::customResourceLoader);
                com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document(targetStream, loadOptions);
                pdfDocument.optimizeResources();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                pdfDocument.save(bos);
                bos.close();
                pdfDocument.close();
                return bos.toByteArray();
            } catch (Exception e) {
                log.error(String.format("Exception(HtmlToPdf.convertHtmlToPdf) %s", ExceptionUtils.getMessage(e)));
            }
        }
        return new byte[0];
    }

    public static ByteArrayOutputStream encryptPDF(byte[] src, String password) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        if ((src != null) && (src.length > 0) && (!StringUtils.isEmpty(password))) {
            Document document = new Document(src);
            DocumentPrivilege documentPrivilege = DocumentPrivilege.getForbidAll();
            documentPrivilege.setAllowCopy(true);
            documentPrivilege.setAllowPrint(true);
            documentPrivilege.setAllowScreenReaders(true);
            document.encrypt(password, "owner", documentPrivilege, CryptoAlgorithm.AESx128, true);
            document.save(bos);
        }
        return bos;
    }
}


*Test routine:*
     @Test
    public void testPDFGenerationFromHTML() throws IOException {
        String outputFileName = "/home/stiaan/Downloads/combined.pdf";
        String testHtmlFile = "Provided in message";

        //String html = createEmailHeaderAsHtml() + createEmptyLine() + wrapMessage(readFile(testHtmlFile));
        String html = wrapMessage(readFile(testHtmlFile));
        System.out.println("HTML2PDF start...");
        long startTime = System.nanoTime();
        byte[] pdf = HtmlToPdf.convertHtmlToPdf(html);
        long endTime = System.nanoTime();
        long duration = (endTime - startTime) / 1000000;
        System.out.println("HTML2PDF took: " + duration + " ms");
        //byte[] pdf = convertHtmlToPdf(new String[]{sampleHtml2});
        if (pdf.length > 0) {
            File outputFile = new File(outputFileName);
            try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
                outputStream.write(pdf);
            }
        }
    }   

HTML File:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<meta name="Author" content="Designer 23.0.4  build 123"/>
<meta name="meta_date" content="01/20/2025"/>
<title>LongTermDisc</title>
</head>
<body>
<table cellspacing="0" style="width:100.0000%;background-color:#ffffff;border-collapse:collapse;margin:0;padding:0;">
<tr><td style="padding-top:4.00px;padding-left:0.00px;padding-right:0.00px;padding-bottom:0.00px;width:786.00px;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;margin-left:23.00px;" name="Main 2">
<tr>
<td width="737" height="273"  valign="top" style="font-size:0;height:273.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Table 6">
<tr>
<td width="737" height="210"  valign="top" style="font-size:0;height:210.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.00;"><img align="center" width="737" height="210" style="width:737.00px;height:210.00px;" src="https://content.momentum.co.za/content/images/banner/ImportantNoticeBanner.png"  alt=""/>
</p>
</td>
</tr>
</table>
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Table 8">
<tr>
<td width="737" height="47"  valign="top" style="font-size:0;height:47.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:right;margin-top:0.00px;margin-bottom:16.00px;margin-left:0.00px;margin-right:8.00px;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">20 January 2025</span></p>
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Table 2">
<tr>
<td width="378" height="15"  valign="top" style="font-size:0;height:15.00px;width:378.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Hello&nbsp;</span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Suzanne</span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">,</span></p>
</td>
<td width="359" height="15"  valign="top" style="font-size:0;height:15.00px;width:359.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:right;margin-top:0.00px;margin-bottom:0.00px;margin-left:0.00px;margin-right:8.00px;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Client number:&nbsp;</span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">1111113393402</span></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table height="16" width="1"  cellspacing="0" style="width:1.00px;border-collapse:collapse;margin:0;padding:0;height:16.00px;" name="dummy_table">
<tr>
<td width="1" height="16"   style="font-size:0;height:16.00px;width:1.00px;padding:0;">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="89"  valign="top" style="font-size:0;height:89.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="As Communicated">
<tr>
<td width="737" height="84"  valign="top" style="font-size:0;height:84.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">As&nbsp;</span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; "><a style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10;" href="https://content-riskcloud.momentum.co.za/Longterm_protected_discount_client_communication_V3.pdf" target="_self"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10;">communicated in January 2024</a></span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">,</span><span style="
	font-size:10.00pt;font-family:Verdana;font-style:normal;font-weight:bold;line-height:1.10; ">&nbsp;</span><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">your premium discount will gradually transition through small yearly discount adjustments until you reach your long-term-protected discount. The next small adjustment to your discount will take effect with your February 2025 debit order. This transition follows the de-linking of Myriad discounts from Multiply Premier membership on 1 January 2024 and the subsequent transition to the long-term-protected discount, which offers enhanced premium certainty.</span></p>
</td>
</tr>
</table>
<table height="4" width="1"  cellspacing="0" style="width:1.00px;border-collapse:collapse;margin:0;padding:0;height:4.00px;" name="dummy_table">
<tr>
<td width="1" height="4"   style="font-size:0;height:4.00px;width:1.00px;padding:0;">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="92"  valign="top" style="font-size:0;height:92.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="A Reminder">
<tr>
<td width="737" height="84"  valign="top" style="font-size:0;height:84.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:bold;line-height:1.10; ">A reminder of how the long-term-protected discount is calculated</span></p>
<p style="text-align:left;margin:0;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">Starting on 1 January 2024, your discount percentage experienced an initial reduction of 5 percentage points. This will be followed by subsequent decreases of 2.5 percentage points per year until you reach your long-term-protected discount. Your final position on the Multiply Premier Myriad discount grid as of 1 January 2024 determined the long-term-protected discount you will transition to.</span></p>
</td>
</tr>
</table>
<table height="8" width="1"  cellspacing="0" style="width:1.00px;border-collapse:collapse;margin:0;padding:0;height:8.00px;" name="dummy_table">
<tr>
<td width="1" height="8"   style="font-size:0;height:8.00px;width:1.00px;padding:0;">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="292"  valign="top" style="font-size:0;height:292.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Long Term">
<tr>
<td width="737" height="284"  valign="top" style="font-size:0;height:284.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin-top:0.00px;margin-bottom:8.00px;margin-left:0.00px;margin-right:0.00px;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:bold;line-height:1.10; ">Long-term-protected discount grid</span></p>
<p style="text-align:left;margin:0;line-height:1.10;"><img align="center" width="643" height="259" style="width:643.00px;height:259.00px;" src="https://content.momentum.co.za/content/images/banner/DiscountGrid.png"  alt=""/>
</p>
</td>
</tr>
</table>
<table height="8" width="1"  cellspacing="0" style="width:1.00px;border-collapse:collapse;margin:0;padding:0;height:8.00px;" name="dummy_table">
<tr>
<td width="1" height="8"   style="font-size:0;height:8.00px;width:1.00px;padding:0;">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="142"  valign="top" style="font-size:0;height:142.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<table  width="737" align="left" cellspacing="0" style="width:737.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Accessing">
<tr>
<td width="737" height="142"  valign="top" style="font-size:0;height:142.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin-top:0.00px;margin-bottom:0.00px;margin-left:0.00px;margin-right:19.00px;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:bold;line-height:1.00; ">Accessing your Myriad premium discount information</span></p>
<p style="text-align:left;margin:0;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">To conveniently view your premium discounts, log in to your product portfolio on momentum.co.za. Navigate to the &#39;Life Insurance&#39; tile, click on any benefit dropdown menu, and select &#39;Myriad&#39; to access your Myriad portfolio. Locate the &#39;Discount/ Momentum Interactive&#39; tile at the top right of the screen and select &#39;View details&#39; at the bottom to review your premium discount. The &#39;How was the discount percentage calculated&#39; link will show what Multiply detail was locked in for your future long-term-protected discount.</span></p>
<p style="text-align:left;margin-top:8.00px;margin-bottom:0.00px;margin-left:0.00px;margin-right:0.00px;line-height:1.10;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.10; ">If you have any questions or require further information about the long-term-protected discount, please contact your Financial Adviser or feel free to reach out to our Contact Centre on 0860 665 432.</span></p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="162"  valign="top" style="font-size:0;height:162.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin-top:16.00px;margin-bottom:0.00px;margin-left:0.00px;margin-right:0.00px;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Warm regards,</span></p>
<table height="5" width="1"  cellspacing="0" style="width:1.00px;border-collapse:collapse;margin:0;padding:0;height:5.00px;" name="dummy_table">
<tr>
<td width="1" height="5"   style="font-size:0;height:5.00px;width:1.00px;padding:0;">
</td>
</tr>
</table>
<table  width="378" align="left" cellspacing="0" style="width:378.00px;border-collapse:collapse;
	border-radius:0.00px 0.00px 0.00px 0.00px;" name="Signature">
<tr>
<td width="378" height="79"  valign="top" style="font-size:0;height:79.00px;width:378.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.00;"><img align="center" width="76" height="75" style="width:76.00px;height:75.00px;" src="https://content.momentum.co.za/content/images/banner/SignatureAnnelineCross.png"  alt=""/>
</p>
</td>
</tr>
<tr>
<td width="378" height="46"  valign="top" style="font-size:0;height:46.00px;width:378.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin:0;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Manager</span></p>
<p style="text-align:left;margin:0;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Head: Myriad Contact Centre</span></p>
<p style="text-align:left;margin:0;line-height:1.00;"><span style="
	font-size:10.00pt;font-family:Arial;font-style:normal;font-weight:normal;line-height:1.00; ">Momentum Life Insurance</span></p>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="737" height="157"  valign="top" style="font-size:0;height:157.00px;width:737.00px;
	background-color:#FFFFFF;padding:0;">
<p style="text-align:left;margin-top:24.00px;margin-bottom:0.00px;margin-left:0.00px;margin-right:0.00px;line-height:1.00;"><a style="width:720.00px;height:133.00px;" href="http://www.momentum.co.za"><span style="width:720.00px;height:133.00px;"><img align="center" width="720" height="133" style="width:720.00px;height:133.00px;" src="https://content.momentum.co.za/content/images/banner/MyriadOtpEmailFooter.png"  alt=""/>
</a></p>
</td>
</tr>
</table>
</td></tr></table>
</body>
</html>

@stiaanpretorius

We were unable to notice any issues while testing the scenario in our environment. We did notice an exception i.e. java.net.SocketTimeoutException: connect timed out but it was due to inaccessible image from the URL present in HTML. The PDF however was generated without images and it is also attached here for your kind reference.

testfile.pdf (199.7 KB)

Can you please check again at your end and make sure if some other program routine is causing such issue? Please create a sample console application that is able to reproduce the issue and share it with us in .zip format so that we can test the scenario again to reproduce the issue of OOM and address it accordingly.

AsposeHTML2PDF.zip (336.6 KB)

Please extract, and run the console application from IntelliJ, if possible. It will produce the results as listed below in Test 1 and Test1. All tests were performed on Java 17.

In the console app I have used Aspose and iText to do a comparison between the two. After running the tests, I realised as to why I got a heap error.

Some stats:
Test 1:
First result using the latest iText library(6.1.0) and the previous library of Aspose (24.9):

Starting to test ASPOSE HTML2PDF…
ASPOSE HTML2PDF took: 7109 ms
Ending test ASPOSE HTML2PDF…

Starting to test iText HTML2PDF…
iText HTML2PDF took: 986 ms
Ending test iText HTML2PDF…

Please note the time difference.

Here are the file sizes:
image.png (13.2 KB)

Test 2:
Second result using the latest iText library(6.1.0) and the latest library of Aspose (25.1):

Starting to test ASPOSE HTML2PDF…
ASPOSE HTML2PDF took: 36373 ms
Ending test ASPOSE HTML2PDF…

Starting to test iText HTML2PDF…
iText HTML2PDF took: 1036ms
Ending test iText HTML2PDF…

Please note the time difference now.

Here are the file sizes:
image.png (13.3 KB)

Summary:
As you can see, having a 40MB PDF file, which should in fact be 200+Kb, will cause heap problems. By comparing the two, it is clear that there is something wrong with the 25.1 Java PDF library.

@stiaanpretorius

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PDFJAVA-44770

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Thank you so much.