2016-07-26 5 views
1

Большинство примеров iText7 относятся к использованию PdfFontFactory.createFont() для получения дескрипторов экземпляров PdfFont для текстовых операций. С умеренностью это прекрасно ... но PdfFont - довольно тяжелый объект (PdfEncoding), который, похоже, не уходит, пока PdfDocument не будет закрыт. Таким образом, следующий невинный блок собирается сожрать память:Стратегия iText7 для ограничения потребления памяти PdfFont

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

тривиальная попытка решения с использованием статики не удалось, так как она экземпляры PdfFont не могут быть использованы в более чем одном PdfDocument. И поскольку мой действительный случай более сложный, чем пример выше, я не хочу передавать кучу ссылок PdfFont через довольно глубокий стек.

  1. в API iText7, нет никакого способа перебора существующих PdfFont годов для PdfDocument (есть?)
  2. правило для использования PdfFont просто, что а) он может быть использован столько раз, сколько вы хотите б) в пределах одного PdfDocument экземпляра

(т.е. является возможным решением здесь просто кэш экземпляров PdfFont с помощью ключа PdfDocument + PdfFontProgram?)

+0

приведенный выше кеш-код - плохая идея. Похоже, что экземпляры FontProgram кэшируются в статической карте, что означает, что кэш-ключ weakRef всегда будет использоваться (и в результате будет держать PdfDocument в памяти тоже). Лучший подход - это карта карт - WeakHashMap > –

ответ

0

PdfFonts кажутся кэшируемым/многоразовый на уровне PdfDocument. Если использовать WeakHashMap в качестве кеша, то и ключи, и значения должны быть слабыми ref. например

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(); 
} 

уход также должны быть приняты для IText API, который вызывает PdfFontFactory себя, такие как производные Barcode1D настроенными, чтобы показать удобочитаемое значение (то есть создание нового экземпляра Barcode1D на странице ш/выход вызова SetFont() будет быстро исчерпайте память для больших документов)