iText7 限制 PdfFont 内存消耗的策略

iText7 strategy for limiting memory consumption of PdfFont

大多数 iText7 示例都提到了使用 PdfFontFactory.createFont() 来获取 PdfFont 实例的句柄以进行文本操作。适度,这很好......但是 PdfFont 是一个非常重量级的对象(PdfEncoding),在 PdfDocument 关闭之前似乎不会消失。所以下面的无辜块会吞噬内存:

for (int i = 0; i < someLargeNumber; i++) {
    list.add(
        new ListItem("never gonna give")
        .setFont(PdfFontFactory.createFont("Helvetica-Oblique"))
    )
}

使用静态解决方案的一次微不足道的尝试失败了,因为 PdfFont 实例似乎不能跨多个 PdfDocument 使用。而且因为我的实际案例比上面的例子更复杂,我不想在一个很深的堆栈中传递一堆 PdfFont 引用。

  1. 在 iText7 API 中,没有办法为 PdfDocument 迭代现有的 PdfFont(是吗?)
  2. PdfFont 的使用规则只是 a) 它可以根据需要使用多次 b) 在单个 PdfDocument 实例中

(即这里是否有可能使用 PdfDocument + PdfFontProgram 键缓存 PdfFont 实例的可能解决方案?)

PdfFonts 在 PdfDocument 级别似乎是 cacheable/reusable。如果使用 Wea​​kHashMap 作为缓存,则 Keys 和 Values 都需要是弱引用。例如

private static WeakHashMap<PdfDocument, Map<String, WeakReference<PdfFont>>> fontCache = new WeakHashMap<>();

public static synchronized PdfFont createFont(PdfDocument forDocument, String path) throws IOException {
    Map<String, WeakReference<PdfFont>> documentFontMap = fontCache.get(forDocument);
    if (documentFontMap == null) {
        documentFontMap = new HashMap<>();
        fontCache.put(forDocument, documentFontMap);
    }
    WeakReference<PdfFont> font = documentFontMap.get(path);
    if (font == null) {
        font = new WeakReference<>(PdfFontFactory.createFont(path));
        documentFontMap.put(path, font);
    }
    return font.get();
}

还应注意调用 PdfFontFactory 本身的 iText API,例如配置为显示人类可读值的 Barcode1D 派生词(即每页创建一个新的 Barcode1D 实例 w/out 调用 setFont( ) 将很快耗尽大型文档的内存)