升级到11.4.6会导致java.lang.NoClassDefFoundError:无法初始化类org.docx4j.



案例:使用WordprocessingMLPackage将docx编写为pdf,并使用org.docx4j.fonts中的IdentityPlusMapper()设置fontMapper来映射我们收到的文档中的字体:

java.lang.NoClassDefFoundError: Could not initialize class org.docx4j.fonts.IdentityPlusMapper

位于:getFontMapper()

这种情况发生在从docx4j11.2.8升级到11.4.6之后。

使用中的依赖项有:

org.docx4j:docx4j-core:11.4.6
org.docx4j:docx4j-export-fo:11.4.6
org.docx4j:docx4j-JAXB-ReferenceImpl:11.4.6

这已经是一个已知的问题了吗?

期待可能的答复!

提前谢谢。

此断言错误出现在我们使用的IdentityPlusMapper或BestMatchingMapper的静态块中。确切的线路是:

PhysicalFonts.discoverPhysicalFonts();

该问题的解决方案是使用字体选择正则表达式限制字体在静态块之前加载,如:的javadoc中所述

PhysicalFonts.setRegex()

以下方法快速解决了这个问题,同时减少了内存利用率和静态块的执行时间:

WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
.load(new ByteArrayInputStream(os.toByteArray()));
String fontRegex = ".*(Courier New|Arial|Times New Roman|Comic Sans|Georgia|Impact|Lucida Console|Lucida Sans Unicode|Palatino Linotype|Tahoma|Trebuchet|Verdana|Symbol|Webdings|Wingdings|MS Sans Serif|MS Serif).*";

if(System.getProperty("os.name").startsWith("Windows")) {
fontRegex = ".*(calibri|cour|arial|times|comic|georgia|impact|LSANS|pala|tahoma|trebuc|verdana|symbol|webdings|wingding).*";
}
PhysicalFonts.setRegex(fontRegex);
wordMLPackage.setFontMapper(new BestMatchingMapper());
Docx4J.toPDF(wordMLPackage, outputStream);

这似乎是一个字体加载问题。我在Mac(最新的蒙特利)上,我在构造函数调用中遇到了同样的异常:

java.lang.AssertionError: 
Expecting code not to raise a throwable but caught
java.lang.AssertionError
at org.docx4j.fonts.fop.complexscripts.fonts.GlyphPositioningTable$DeviceTable.<init>(GlyphPositioningTable.java:1778)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readPosDeviceTable(OTFAdvancedTypographicTableReader.java:1729)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readPosAnchor(OTFAdvancedTypographicTableReader.java:2053)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readMarkToLigaturePosTableFormat1(OTFAdvancedTypographicTableReader.java:2347)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readMarkToLigaturePosTable(OTFAdvancedTypographicTableReader.java:2373)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readGPOSSubtable(OTFAdvancedTypographicTableReader.java:3124)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readLookupTable(OTFAdvancedTypographicTableReader.java:3193)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readLookupList(OTFAdvancedTypographicTableReader.java:3220)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readCommonLayoutTables(OTFAdvancedTypographicTableReader.java:3241)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readGPOS(OTFAdvancedTypographicTableReader.java:3501)
at org.docx4j.fonts.fop.complexscripts.fonts.OTFAdvancedTypographicTableReader.readAll(OTFAdvancedTypographicTableReader.java:88)
at org.docx4j.fonts.fop.fonts.truetype.OpenFont.handleCharacterSpacing(OpenFont.java:895)
at org.docx4j.fonts.fop.fonts.truetype.OpenFont.readFont(OpenFont.java:867)
at org.docx4j.fonts.fop.fonts.truetype.OFFontLoader.read(OFFontLoader.java:121)
at org.docx4j.fonts.fop.fonts.truetype.OFFontLoader.read(OFFontLoader.java:105)
at org.docx4j.fonts.fop.fonts.FontLoader.getFont(FontLoader.java:130)
at org.docx4j.fonts.fop.fonts.FontLoader.loadFont(FontLoader.java:114)
at org.docx4j.fonts.fop.fonts.autodetect.FontInfoFinder.find(FontInfoFinder.java:262)
at org.docx4j.fonts.PhysicalFonts.getPhysicalFont(PhysicalFonts.java:307)
at org.docx4j.fonts.PhysicalFonts.addPhysicalFonts(PhysicalFonts.java:246)
at org.docx4j.fonts.PhysicalFonts.addPhysicalFont(PhysicalFonts.java:236)
at org.docx4j.fonts.PhysicalFonts.discoverPhysicalFonts(PhysicalFonts.java:183)
at org.docx4j.fonts.IdentityPlusMapper.<clinit>(IdentityPlusMapper.java:74)
at foo(...)
open fun foo(...) {
...
val mlPackage = WordprocessingMLPackage.load(ByteArrayInputStream(input))
mlPackage.fontMapper = IdentityPlusMapper() //<-- boom
}

更新(2022年8月29日):我通过将Docx4j升级到11.4.7解决了这个问题。此外,我必须在调用Docx4J.toFO(...):之前添加以下代码

val fopFactoryBuilder: FopFactoryBuilder = FORendererApacheFOP.getFopFactoryBuilder(foSettings)
FORendererApacheFOP.getFOUserAgent(foSettings, fopFactoryBuilder.build())

我已经通过为Mac中可用的字体设置regex来修复了这一问题,PhysicalFonts class set regex方法也推荐了这一点。

PhysicalFonts.regex = ".*(Courier New|Arial|Times New Roman|Comic Sans|Georgia|Impact|Lucida Console|Lucida Sans Unicode|Palatino Linotype|Tahoma|Trebuchet|Verdana|Symbol|Webdings|Wingdings|MS Sans Serif|MS Serif).*"

最新更新