Java11没有字体?

Java 11 does not have fonts?

我正在使用 Java 11 Corretto + Spring Boot with Apache POI 但我在 AWS Lambda 上使用时遇到问题。如果我 运行 作为“正常” API 工作正常,但当 运行 在 AWS lambda 中使用 servless 时失败。

try (ByteArrayOutputStream out = new ByteArrayOutputStream(); SXSSFWorkbook workbook = new SXSSFWorkbook(1000)) {
    SXSSFSheet sheet = workbook.createSheet("test"); //error here!!
    } ...

Caused by: java.lang.Error: Probable fatal error: No physical fonts found. at java.desktop/sun.font.SunFontManager.lambda$getDefaultPhysicalFont[=16=](Unknown Source) at java.base/java.util.Optional.orElseThrow(Unknown Source) at java.desktop/sun.font.SunFontManager.getDefaultPhysicalFont(Unknown Source) at java.desktop/sun.font.CompositeFont.doDeferredInitialisation(Unknown Source) at java.desktop/sun.font.CompositeFont.getSlotFont(Unknown Source) at java.desktop/sun.font.CompositeGlyphMapper.initMapper(Unknown Source) at java.desktop/sun.font.CompositeGlyphMapper.(Unknown Source) at java.desktop/sun.font.CompositeFont.getMapper(Unknown Source) at java.desktop/sun.font.CompositeFont.canDisplay(Unknown Source) at java.desktop/java.awt.Font.canDisplayUpTo(Unknown Source) at java.desktop/java.awt.font.TextLayout.singleFont(Unknown Source) at java.desktop/java.awt.font.TextLayout.(Unknown Source) at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:285) at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.(AutoSizeColumnTracker.java:117) at org.apache.poi.xssf.streaming.SXSSFSheet.(SXSSFSheet.java:84) at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:705) at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:724)

我试图创建字体修复程序,但我不知道如何继续

@PostConstruct
public void loadFonts() {
    URL configURL = getClass().getClassLoader().getResource("fontconfig.properties");
    String path = configURL != null ? configURL.getPath() : null;
    Properties props = System.getProperties();
    LOGGER.info("Loading font config file: {}", path);
    props.put("sun.awt.fontconfig", path);

    String[] fonts;
    try {
        GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    } catch (Throwable ex) {
        LOGGER.warn("Reloading Fonts");
    }
    try {
        fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();

        for (String font : fonts) {
            LOGGER.info("Available Font: {}", font);
        }
    } catch (Throwable ex) {
        LOGGER.error("Could not load Fonts");
    }
}

配置文件:

version=1
sequence.allfonts=default

在 AWS Lambda 上 运行ning 时,它会向日志输出一些字体,所以我不明白为什么会出现该错误:

2022-05-31 16:00:14  INFO  Starting Lambda Container Handler
2022-05-31 16:00:18  INFO  Loading font config file: /var/task/fontconfig.properties
2022-05-31 16:00:18  INFO  Available Font: Dialog
2022-05-31 16:00:18  INFO  Available Font: DialogInput
2022-05-31 16:00:18  INFO  Available Font: Monospaced
2022-05-31 16:00:18  INFO  Available Font: SansSerif
2022-05-31 16:00:18  INFO  Available Font: Serif

知道如何添加物理字体以及为什么 POI 不能使用输出到日志的可用字体吗?

编辑: 我也尝试 运行 为无头但我得到同样的错误:

`props.setProperty("java.awt.headless", "true");`

字体捆绑

Any idea how to add physical fonts

Oracle JDK 来自 Oracle stopped bundling fonts 的产品 Java 11.

OpenJDK 项目不捆绑字体,至少在最近的版本中没有。

Amazon 产品的 Corretto JDK 基于 OpenJDK 代码库。根据您的报告,显然他们不捆绑字体。

您必须选择:

  • 依赖楼主提供的字体OS.
  • 在您的 Java 应用中捆绑字体。仔细研究许可条款。有些字体允许这样的捆绑,有些则不允许。有些需要收费,有些则不需要。有些需要确认,有些则不需要。
  • 从包含字体的供应商处获得 JDK。

我知道至少有一家这样的供应商:Azul Systems 将字体与其 Azul Platform Core 商业产品捆绑在一起。

可能还有其他我不知道的此类供应商。许多供应商提供 JDK 二进制文件和安装程序。这些供应商包括 Adoptium、SAP、BellSoft、Microsoft、Azul Systems、Amazon、Oracle、Red Hat/IBM、Pivo​​tal 等。

物理字体与逻辑字体

why can't the POI use the available fonts that output to the logs

您在日志中列出的字体是 逻辑 字体,而不是 物理 字体。 Java文档中清楚地记录了 Font class.

的区别

要使用逻辑字体名称,您必须有一些支持物理字体。如果您的应用程序、您的 JDK 或您的主机 OS 中不存在任何字体,则逻辑字体将无法工作。

AWS Lambda 的字体

关于在 AWS Lambda 中提供字体,也许这两页可能会有所帮助。 (感谢 jarmod for the links。)

基本思路是在您的包中创建一个 /fonts 文件夹。在其中包含一个 fonts.conf 文件,其中包含 XML 个配置元素。将捆绑的字体文件放在该配置文件旁边。