Document.convert(OutputStream outputLogStream, PdfFormat format, ConvertErrorAction action) is not thread-safe

I’ve got an issue with the Document.convert(OutputStream outputLogStream, PdfFormat format, ConvertErrorAction action) method in a concurrency scenario. Using this method in parallel throws the following exception:

com.aspose.pdf.internal.ms.System.l7k: Only 3D and 4D CLUT are supported
at com.aspose.pdf.internal.l59l.l0t.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0if.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l1if.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l2if.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l2h.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.(Unknown Source)
at com.aspose.pdf.internal.l2p.lu.(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.internal.l9f.l1n.lI(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.lf(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.l3n(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.l5v(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.ADocument.lI(Unknown Source)
at com.aspose.pdf.Document.lI(Unknown Source)
at com.aspose.pdf.ADocument.convertInternal(Unknown Source)
at com.aspose.pdf.Document.convertInternal(Unknown Source)
at com.aspose.pdf.ADocument.convert(Unknown Source)
at com.aspose.pdf.Document.convert(Unknown Source)
at de.synaxon.asposetest.AsposeTest.convertPdf(AsposeTest.java:48)
at de.synaxon.asposetest.AsposeTest.lambda$main$0(AsposeTest.java:32)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)

class com.aspose.pdf.internal.l59l.l0k: Exception of type System.Exception was thrown.
com.aspose.pdf.internal.l59l.l1t.ld(Unknown Source)
com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
com.aspose.pdf.internal.foundation.rendering.l3u.lI(Unknown Source)
com.aspose.pdf.internal.foundation.rendering.l3u.(Unknown Source)
com.aspose.pdf.internal.l2p.lu.(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
com.aspose.pdf.internal.l9f.l1n.lI(Unknown Source)
com.aspose.pdf.internal.l9k.l1t.lf(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.l3n(Unknown Source)
com.aspose.pdf.internal.l9k.l1t.l5v(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
com.aspose.pdf.ADocument.lI(Unknown Source)
com.aspose.pdf.Document.lI(Unknown Source)
com.aspose.pdf.ADocument.convertInternal(Unknown Source)
com.aspose.pdf.Document.convertInternal(Unknown Source)
com.aspose.pdf.ADocument.convert(Unknown Source)
com.aspose.pdf.Document.convert(Unknown Source)
de.synaxon.asposetest.AsposeTest.convertPdf(AsposeTest.java:48)
de.synaxon.asposetest.AsposeTest.lambda$main$0(AsposeTest.java:32)
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
java.base/java.lang.Thread.run(Thread.java:833)
at com.aspose.pdf.internal.l59l.l1t.ld(Unknown Source)
at com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.(Unknown Source)
at com.aspose.pdf.internal.l2p.lu.(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.internal.l9f.l1n.lI(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.lf(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.l3n(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.l5v(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.ADocument.lI(Unknown Source)
at com.aspose.pdf.Document.lI(Unknown Source)
at com.aspose.pdf.ADocument.convertInternal(Unknown Source)
at com.aspose.pdf.Document.convertInternal(Unknown Source)
at com.aspose.pdf.ADocument.convert(Unknown Source)
at com.aspose.pdf.Document.convert(Unknown Source)
at de.synaxon.asposetest.AsposeTest.convertPdf(AsposeTest.java:48)
at de.synaxon.asposetest.AsposeTest.lambda$main$0(AsposeTest.java:32)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)

The code to reproduce the issue can be found on: Document.convert(OutputStream outputLogStream, PdfFormat format, ConvertErrorAction action) is not thread-safe · Issue #64 · aspose-pdf/Aspose.PDF-for-Java · GitHub

@vmuth

Please note that Aspose.PDF is a multithreaded safe API as long as one PDF file is accessed by only one thread at a time. In other words, one thread should only access one PDF file. If a file is accessed simultaneously by multiple thread, unexpected results will be produced. By looking at your code sample, looks like you are using single file in multiple threads which is not recommended. You can change your approach as per the recommendations and let us know if you still notice any issues.

Hi, thank you for your reply. I’ve customized the code in order to reference 4 different PDF files. Even with four files I can reproduce the error.

This is the new Code:

public class AsposeTest {

private static final Object asposePdfLock = new Object();

public static void main(String[] args) throws IOException, InterruptedException {
    int numberOfThreads = 100;
    ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);

    List<String> pathes = new ArrayList<>();
    pathes.add("/opt/data/testme.pdf");
    pathes.add("/opt/data/testme2.pdf");
    pathes.add("/opt/data/testme3.pdf");
    pathes.add("/opt/data/testme4.pdf");
    
    for (String path: pathes) {
        executorService.submit(() -> {
            try {
                convertPdf(path);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        });
    }

    executorService.shutdown();
}

private static void convertPdf(String path) throws IOException {
    try (InputStream inputStream = new FileInputStream(path); ByteArrayOutputStream a3bOut = new ByteArrayOutputStream()) {

// synchronized (asposePdfLock) {
// Convert and save directly to the output stream
try (Document document = new Document(inputStream)) {
document.convert(a3bOut, PdfFormat.PDF_A_3B, ConvertErrorAction.None);
document.save(a3bOut);
document.close();
} catch (Exception ex) {
ex.printStackTrace();
}
// }
System.err.println("Done with conversion for pdf: " + path);
}

}

}

The exception:

Done with conversion for pdf: /opt/data/testme4.pdf
Done with conversion for pdf: /opt/data/testme3.pdf
class com.aspose.pdf.internal.l59l.l0k: Exception of type System.Exception was thrown.
com.aspose.pdf.internal.l59l.l1t.ld(Unknown Source)
com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
com.aspose.pdf.internal.foundation.rendering.l3u.lI(Unknown Source)
com.aspose.pdf.internal.foundation.rendering.l3u.(Unknown Source)
com.aspose.pdf.internal.l2p.lu.(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
com.aspose.pdf.internal.l9f.l1n.lI(Unknown Source)
com.aspose.pdf.internal.l9k.l1t.lf(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.l3n(Unknown Source)
com.aspose.pdf.internal.l9k.l1t.l5v(Unknown Source)
com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
com.aspose.pdf.ADocument.lI(Unknown Source)
com.aspose.pdf.Document.lI(Unknown Source)
com.aspose.pdf.ADocument.convertInternal(Unknown Source)
com.aspose.pdf.Document.convertInternal(Unknown Source)
com.aspose.pdf.ADocument.convert(Unknown Source)
com.aspose.pdf.Document.convert(Unknown Source)
de.synaxon.asposetest.AsposeTest.convertPdf(AsposeTest.java:52)
de.synaxon.asposetest.AsposeTest.lambda$main$0(AsposeTest.java:36)
java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
java.base/java.lang.Thread.run(Thread.java:833)
at com.aspose.pdf.internal.l59l.l1t.ld(Unknown Source)
at com.aspose.pdf.internal.l59l.l1t.lI(Unknown Source)
at com.aspose.pdf.internal.l59l.l0p.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.lI(Unknown Source)
at com.aspose.pdf.internal.foundation.rendering.l3u.(Unknown Source)
at com.aspose.pdf.internal.l2p.lu.(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.internal.l9f.l1n.lI(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.lf(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.l3n(Unknown Source)
at com.aspose.pdf.internal.l9k.l1t.l5v(Unknown Source)
at com.aspose.pdf.internal.l9k.l1if.lI(Unknown Source)
at com.aspose.pdf.ADocument.lI(Unknown Source)
at com.aspose.pdf.Document.lI(Unknown Source)
at com.aspose.pdf.ADocument.convertInternal(Unknown Source)
at com.aspose.pdf.Document.convertInternal(Unknown Source)
at com.aspose.pdf.ADocument.convert(Unknown Source)
at com.aspose.pdf.Document.convert(Unknown Source)
at de.synaxon.asposetest.AsposeTest.convertPdf(AsposeTest.java:52)
at de.synaxon.asposetest.AsposeTest.lambda$main$0(AsposeTest.java:36)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Done with conversion for pdf: /opt/data/testme.pdf
Done with conversion for pdf: /opt/data/testme2.pdf

@vmuth

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-45022

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.