linux環境下new SXSSFWorkbook(XSSFWorkbook workbook)失敗

使用場景

  項目開發的時候需要導出一個寫死數據很多的報表,考慮到寫死數據的開發成本,如果能夠直接從workbook中讀取需要的數據,豈不是美滋滋?

 

實際操作中遇到的問題

項目開發完了之後,在Mac OS X環境下完美運行,但是項目一上線,就報了一個空指針異常

java.lang.NullPointerException: null
	at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[?:1.8.0_212]
	at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) ~[?:1.8.0_212]
	at sun.awt.FontConfiguration.init(FontConfiguration.java:107) ~[?:1.8.0_212]
	at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) ~[?:1.8.0_212]
	at sun.font.SunFontManager$2.run(SunFontManager.java:431) ~[?:1.8.0_212]
	at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_212]
	at sun.font.SunFontManager.<init>(SunFontManager.java:376) ~[?:1.8.0_212]
	at sun.awt.FcFontManager.<init>(FcFontManager.java:35) ~[?:1.8.0_212]
	at sun.awt.X11FontManager.<init>(X11FontManager.java:57) ~[?:1.8.0_212]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_212]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_212]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_212]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_212]
	at java.lang.Class.newInstance(Class.java:442) ~[?:1.8.0_212]
	at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) ~[?:1.8.0_212]
	at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_212]
	at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[?:1.8.0_212]
	at java.awt.Font.getFont2D(Font.java:491) ~[?:1.8.0_212]
	at java.awt.Font.canDisplayUpTo(Font.java:2060) ~[?:1.8.0_212]
	at java.awt.font.TextLayout.singleFont(TextLayout.java:470) ~[?:1.8.0_212]
	at java.awt.font.TextLayout.<init>(TextLayout.java:531) ~[?:1.8.0_212]
	at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:273) ~[poi-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:82) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:661) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.<init>(SXSSFWorkbook.java:249) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.<init>(SXSSFWorkbook.java:213) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.<init>(SXSSFWorkbook.java:188) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at org.apache.poi.xssf.streaming.SXSSFWorkbook.<init>(SXSSFWorkbook.java:163) ~[poi-ooxml-4.0.0.jar!/:4.0.0]
	at com.whatsegg.egg.repair.service.impl.RepairReportFormServiceImpl.getWorkbook(RepairReportFormServiceImpl.java:205) ~[classes!/:0.01]

仔細讀讀異常信息

可以獲取到的信息有:

1.最外層,是在我嘗試獲取Workbook的時候報錯的

2.SXSSFWorkbook層,是在SXSSFWorkbook的構造器中報的錯,那應該就是在我獲取完XSSFWorkbook(SXSSFWorkbook因爲自身存在的目的,對讀取的支持非常的少,所以如果需要讀取數據,還是要使用XSSFWorkbook來獲取信息),利用XSSFWorkbook來new SXSSFWorkbook的時候報錯的

3.再往上看,可以發現poi在調用sun的包下的代碼裏出錯的,這是基礎jar包的問題,我們也可以看到,服務器上的java版本是1.8.0_212(而我自己的java版本是 "1.8.0_201")

那麼從獲取到的信息可以推理出,第一這應該不是我的鍋,第二可能是java版本不同導致了這個問題,我謹慎地跟着異常想要追蹤,發現 sun.font.FontManagerFactory 這個類裏頭會根據系統不同來選擇不同的字體管理器類,這也可能是一個異常點。

 


二更,發現這個問題的原因了。過程如下:

1. 重新更新了jre和jdk妄圖復現linux上的問題,復現失敗。
2. 前輩說可以在docker上覆現,於是重新撿起了docker,自己建了鏡像和容器,運行,復現失敗。
3. 前輩發現了docker的配置文件和我自己的“官方複製版”不一樣!原來我們使用的是openjdk:8-jdk-alpine!

在參考其他項目,重新構建鏡像的時候,發現docker的配置文件中,有一個字體的配置

RUN apk –update add curl bash openjdk8 ttf-dejavu tini git && \
rm -rf /var/cache/apk/*

前輩是全棧工程師,他敏感地發現ttf-dejavu是個字體配置文件,於是破案了,線上環境用的也是docker容器來實現分佈式服務,但是我們這個項目的Dockerfile裏頭就沒有加入這段環境配置,導致程序找不到字體庫,報了空指針異常。

在docker裏頭加上這一段應該就行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章