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);// StylesFont 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 1Row 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.InvocationTargetExceptionat 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.InvocationTargetExceptionat 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.InvocationTargetExceptionat 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.NullPointerExceptionat 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.InvocationTargetExceptionat 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)Jat 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 就不会报错了.