You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PDFBOX增量签名时间歇性出现COSStream已关闭异常求助

PDFBox 增量签名间歇性抛出 COSStream 已关闭异常

问题描述

使用PDFBox执行PDF签名操作,调用saveIncrementalForExternalSigning方法前已添加验证信息,相关代码如下:

public ByteArrayOutputStream addSignature(PDDocument document, PDSignature signature, InputStream inputStream,
                                          SealCSCCredentialOptions cscCredentialOptions, Certificate[] certificateChain, String signatureFormat)
        throws Exception {

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    ExternalSigningSupport externalSigningSupport = null;
    try {
        externalSigningSupport = document.saveIncrementalForExternalSigning(outputStream);
    } catch (IOException e)
    {
        e.printStackTrace();
        LOG.error("Request ID: {} Error occurred: " + e.getMessage(), LoggerUtils.getFromThreadContext("requestId"));
        throw e;
    }

    CMSSignedData signedData = generateCMSSignedData(certificateChain, externalSigningSupport, inputStream,
            cscCredentialOptions, signatureFormat);

    byte[] cmsSignature = signedData.getEncoded();
    externalSigningSupport.setSignature(cmsSignature);
    
    return outputStream;
}

但在调用externalSigningSupport = document.saveIncrementalForExternalSigning(outputStream);时,间歇性出现异常:COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed? 该错误并非每次出现,有时能成功返回结果。

排查方向与原因分析

1. PDDocument 实例的并发访问或重复使用问题

这个异常最常见的根源是同一个PDDocument实例被多个线程共享、重复调用关闭方法,或者在签名流程之外被意外关闭。由于问题是间歇性出现,大概率是存在线程安全问题:

  • 如果该方法被多线程调用,且传入的是同一个PDDocument实例,就可能出现一个线程还在操作流,另一个线程已经关闭了文档或流的情况。
  • 检查调用addSignature的上游逻辑,是否存在文档被提前关闭(比如try-with-resources块的范围不合理),或者签名完成后没有正确隔离实例,导致后续操作意外关闭了流。

2. PDFBox 内部流的生命周期管理问题

saveIncrementalForExternalSigning方法会操作PDF内部的COSStream,若之前对文档的操作(比如添加验证信息的步骤)没有正确处理流的关闭,可能导致部分流处于不稳定状态:

  • 检查添加验证信息的代码,是否存在手动关闭了文档内部的COSStream但没有重新获取的情况。
  • PDFBox的PDDocument在操作过程中会缓存部分流,若内存不足或GC触发时,可能会自动关闭未使用的流,这种情况下也会间歇性触发异常。

3. 输入流的异常处理问题

传入的inputStream如果在其他地方被共享或提前关闭,也可能间接影响文档内部流的状态。需要确保:

  • 每个签名请求使用独立的InputStream实例,且在签名流程完成前不会被关闭。
  • generateCMSSignedData方法中是否存在对externalSigningSupport的流进行不当操作(比如提前关闭)。

修复建议

  • 确保PDDocument实例的唯一性:每个签名请求使用独立的PDDocument实例,避免多线程共享同一个实例,且在签名完成后单独关闭文档(注意不要在当前方法内关闭,因为调用方可能还需要使用)。
  • 检查上游资源管理:确认调用addSignature的代码没有在try-with-resources中提前关闭文档,或者在签名流程未完成时触发了文档的关闭操作。
  • 避免手动操作内部流:不要直接关闭或操作PDDocument内部的COSStream,交给PDFBox自行管理生命周期。
  • 添加线程安全控制:如果必须多线程处理,对PDDocument实例的操作添加同步锁,确保同一时间只有一个线程操作该实例。

内容的提问来源于stack exchange,提问作者Tanmay Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 19:35:26