Ubuntu/Centos下OpenJ9 POI输出Excel的Bug

项目更换 JDK为 OpenJ9 后, 使用 POI 导出 Excel 遇到的问题

OpenJ9 版本信息

/opt/jdk/jdk-11.0.17+8/bin/java -version
openjdk version "11.0.17" 2022-10-18
IBM Semeru Runtime Open Edition 11.0.17.0 (build 11.0.17+8)
Eclipse OpenJ9 VM 11.0.17.0 (build openj9-0.35.0, JRE 11 Linux amd64-64-Bit Compressed References 20221031_559 (JIT enabled, AOT enabled)
OpenJ9   - e04a7f6c1
OMR      - 85a21674f
JCL      - a94c231303 based on jdk-11.0.17+8)

问题描述

使用下面的代码, 通过 SXSSFWorkbook 实例生成 2017格式的excel

public static void exportToExcel(String fileName) {
    SXSSFWorkbook workbook = new SXSSFWorkbook();
    Sheet sheet = workbook.createSheet("English Tab");
    Row header = sheet.createRow(0);
    // Styles
    Font font = workbook.createFont();
    font.setFontName("Arial");
    font.setFontHeightInPoints((short) 12);
    CellStyle cellStyle = workbook.createCellStyle();
    cellStyle.setFont(font);

    Cell headerCell = header.createCell(0);
    headerCell.setCellValue("Name");
    headerCell.setCellStyle(cellStyle);

    headerCell = header.createCell(1);
    headerCell.setCellValue("Age");
    headerCell.setCellStyle(cellStyle);

    // Row 1
    Row row = sheet.createRow(1);
    Cell cell = row.createCell(0);
    cell.setCellValue("John Smith");
    cell.setCellStyle(cellStyle);

    cell = row.createCell(1);
    cell.setCellValue(20);
    cell.setCellStyle(cellStyle);

    File currDir = new File(".");
    String path = currDir.getAbsolutePath();
    String fileLocation = path.substring(0, path.length() - 1) + fileName;

    try (FileOutputStream outputStream = new FileOutputStream(fileLocation)) {
        workbook.write(outputStream);
    } catch (IOException e) {
        log.error(e.getMessage(), e);
    }
}

报错如下, 在 Ubuntu22.04 和 Centos7 下都会报同样的错

/opt/jdk-11.0.17+8/bin/java -jar j9test.jar
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.InternalError: java.lang.reflect.InvocationTargetException
	at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:86)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
	at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
	at java.desktop/sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:190)
	at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:224)
	at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:252)
	at java.desktop/sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:75)
	... 8 more
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:84)
	... 15 more
Caused by: java.lang.NullPointerException
	at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
	at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:225)
	at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:107)
	at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:719)
	at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:379)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
	at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:324)
	at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
	at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)
	... 20 more

解决方法

对于 Ubuntu, 安装 libfontconfig1 后问题解决

sudo apt install libfontconfig1

如果没有dejavu字体, 也需要安装

sudo apt install ttf-dejavu

对于 Centos, 安装 dejavu-sans 字体和 fontconfig 后问题解决

sudo yum install dejavu-sans-fonts fontconfig

对应Centos的版本信息为

# uname -a
Linux localhost.localdomain 3.10.0-1160.49.1.el7.x86_64 #1 SMP Tue Nov 30 15:51:32 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
You have mail in /var/spool/mail/root

另一种错误 UnsatisfiedLinkError: sun/font/SunLayoutEngine.createFace

这是在几台版本较低的 Centos7 服务器上出现的, Centos版本信息为

# uname -a
Linux app02v 3.10.0-1127.19.1.el7.x86_64 #1 SMP Tue Aug 25 17:23:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

# uname -a
Linux bogon 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

错误内容

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.UnsatisfiedLinkError: sun/font/SunLayoutEngine.createFace(Lsun/font/Font2D;J)J
	at java.desktop/sun.font.SunLayoutEngine$FaceRef.getNativePtr(SunLayoutEngine.java:202)
	at java.desktop/sun.font.SunLayoutEngine.getFacePtr(SunLayoutEngine.java:162)
	at java.desktop/sun.font.SunLayoutEngine.layout(SunLayoutEngine.java:170)
	at java.desktop/sun.font.GlyphLayout$EngineRecord.layout(GlyphLayout.java:687)
	at java.desktop/sun.font.GlyphLayout.layout(GlyphLayout.java:468)
	at java.desktop/sun.font.ExtendedTextSourceLabel.createGV(ExtendedTextSourceLabel.java:329)
	at java.desktop/sun.font.ExtendedTextSourceLabel.getGV(ExtendedTextSourceLabel.java:315)
	at java.desktop/sun.font.ExtendedTextSourceLabel.createLogicalBounds(ExtendedTextSourceLabel.java:225)
	at java.desktop/sun.font.ExtendedTextSourceLabel.getAdvance(ExtendedTextSourceLabel.java:134)
	at java.desktop/java.awt.font.TextLine.init(TextLine.java:281)
	at java.desktop/java.awt.font.TextLine.<init>(TextLine.java:129)
	at java.desktop/java.awt.font.TextLine.fastCreateTextLine(TextLine.java:978)
	at java.desktop/java.awt.font.TextLayout.fastInit(TextLayout.java:611)
	at java.desktop/java.awt.font.TextLayout.<init>(TextLayout.java:532)
	at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:301)
	at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
	at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:95)
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:726)
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:745)
	... 8 more

这个错误比较奇怪, 尝试过在~/.fonts下增加字体, 以及使用 headless, 都无法解决这个问题. 但是将 SXSSFWorkbook 换成 XSSFWorkbook 就不会报错了.

posted on 2023-02-10 18:06  Milton  阅读(223)  评论(3编辑  收藏  举报

导航