概率性出现COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?

问题描述

在使用XEasyPdf(XEasyPdf是优良的封装Apache PDFBox的工具)写出流时,发生概率性的提示报错:
COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?
对,没错是概率性的,排除代码问题给出下面的解决方案:

发生原因

在使用 Apache PDFBox 中的 PDDocument 进行操作时,如果你确定没有显式地关闭 PDDocument,恰巧此时发生了java的垃圾回收机制就会遇到以下问题:

  1. 在调用 PDDocument 的方法去创建页面PDPage时,会执行COSStream.checkClosed()方法去检查COSStream是否关闭:
private void checkClosed() throws IOException {
    if (this.randomAccess != null && this.randomAccess.isClosed()) {
        throw new IOException("COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed?");
    }
}
  1. 但是如果此时发生了java 垃圾回收调用了 ScratchFileBufferfinalize() 方法,就会导致 randomAccess.isClosed() == true,导致异常抛出。
protected void finalize() throws Throwable {
    try {
        if (this.pageHandler != null && LOG.isDebugEnabled()) {
            LOG.debug("ScratchFileBuffer not closed!");
        }
        
        this.close();
    } finally {
        super.finalize();
    }
}

解决办法—调用 System.gc()(解决了但不推荐)

此时需要及时释放内存,调用 System.gc() 来提示垃圾回收器尽快执行垃圾回收。但是,这并不是一种推荐的做法,因为垃圾回收的时机是由 JVM 决定的,而不是由程序员决定的。最好的做法还是在代码中正确地管理资源,但是目前我的pdf文件构造设计涉及太多,目前只能通过此种方法解决。

解决了

原来是自己有一个流忘了及时关,及时关就不会发现gc了。调用 不需要调用System.gc()

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值