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

PDFBox循环生成PDF:如何仅加载一次字体并重复使用?

问题解答

1. 调用PDType0Font.load(doc, ...)的行为

每次调用该方法时,PDFBox会执行以下操作:

  • 读取传入的字体输入流,完整解析10M大小的TTF文件内容
  • 创建对应的PDType0Font实例,包含字体的字形、编码映射等所有解析后的数据
  • 将该字体实例与当前的PDDocument绑定,作为文档的资源对象存在

2. 是否会创建10000个大字体对象?

是的。循环执行10000次意味着会重复10000次字体解析流程,每次都会生成一个独立的PDType0Font实例,每个实例仅原始字体数据就占用10M内存,加上解析后的额外元数据,内存占用会更高。短时间内大量创建这类大对象会快速耗尽堆内存,频繁触发Full GC,这就是你遇到问题的核心原因。

3. 如何实现字体仅加载一次、循环复用?

可以通过预加载字体到临时文档,再在循环中克隆字体到目标文档的方式实现复用,彻底避免重复解析TTF文件,优化后的代码示例如下:

// 预加载字体数据到字节数组,避免重复从类加载器读取流
byte[] fontBytes;
try (InputStream fontStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("font/simsun.ttf")) {
    // 自行实现流转字节数组,无需第三方依赖
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fontStream.read(buffer)) != -1) {
        baos.write(buffer, 0, len);
    }
    fontBytes = baos.toByteArray();
}

// 创建临时文档预加载字体,仅解析一次TTF
PDDocument tempDoc = new PDDocument();
PDType0Font baseFont = PDType0Font.load(tempDoc, new ByteArrayInputStream(fontBytes));

try {
    for(int i=0; i<10000; ++i){
        PDDocument doc = PDDocument.load(inputstream);
        PDPage page = doc.getPage(0);
        
        // 将预加载的字体克隆到当前文档,复用已解析的字体核心数据
        PDType0Font reusedFont = (PDType0Font) baseFont.cloneForDocument(doc);
        
        PDPageContentStream content = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);
        content.beginText();
        content.setFont(reusedFont, 10);
        // ... 执行你的文本绘制逻辑
        content.endText();
        content.close();
        
        doc.save(outstream);
        doc.close();
    }
} finally {
    // 关闭临时文档,释放资源
    tempDoc.close();
}

核心优化点:

  • 提前将TTF文件读入字节数组,避免循环中重复执行IO操作,提升效率
  • 仅在临时文档中解析一次字体,后续循环通过cloneForDocument方法复用已解析的字体核心数据,仅创建当前文档所需的绑定对象,内存占用大幅降低
  • 严格管理文档资源,确保所有PDDocument都被正确关闭,避免内存泄漏

这样调整后,堆内存中不会再出现大量重复的大字体对象,Full GC频率会显著降低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:54:22