Excel導出工具Apache poi在docker環境中報錯/usr/local/jdk1.8.0_202/jre/lib/amd64/libawt_xawt.so: libXext.so.6: cannot open shared object file: No such file or directory


背景

java現代化編程中,通常會使用CI/CD技術進行項目部署,筆者最近的項目就使用了Jekins部署項目到docker環境中。

由於docker image中的jdk版本比較低,計划升級jdk的版本,以規避JDK 1.8.u1xx系列的bug。

舉例來說,筆者將docker文件中的版本升級到1.8u322,修改Dockerfile為如下

FROM openjdk:8u322-jre

然后使用IDEA的Docker插件發布,正常運行。唯獨使用POI導出Excel時候報錯。如下

2022-03-04 10:37:51.471 [XNIO-1 task-1] DEBUG [com.alibaba.excel.context.WriteContextImpl.finish] - Finished write.
2022-03-04 10:37:51.474 [XNIO-1 task-1] DEBUG [org.springframework.web.servlet.FrameworkServlet.logResult] - Failed to complete request: com.alibaba.excel.exception.ExcelGenerateException: java.lang.UnsatisfiedLinkError: /usr/local/openjdk-8/lib/amd64/libawt_xawt.so: libXext.so.6: cannot open shared object file: No such file or directory
2022-03-04 10:37:51.476 [XNIO-1 task-1] ERROR [io.undertow.servlet.api.LoggingExceptionHandler.handleThrowable] - UT005023: Exception handling request to /API/SAPOrder/exportList
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.alibaba.excel.exception.ExcelGenerateException: java.lang.UnsatisfiedLinkError: /usr/local/openjdk-8/lib/amd64/libawt_xawt.so: libXext.so.6: cannot open shared object file: No such file or directory
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:665) ~[javax.servlet-api-4.0.1.jar!/:4.0.1]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) ~[javax.servlet-api-4.0.1.jar!/:4.0.1]
        at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.websockets.jsr.JsrWebSocketFilter.doFilter(JsrWebSocketFilter.java:173) ~[undertow-websockets-jsr-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:97) ~[spring-web-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at com.www.mes.common.filter.HttpTraceLogFilter.doFilterInternal(HttpTraceLogFilter.java:54) ~[classes!/:0.1-SNAPSHOT]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.1.19.RELEASE.jar!/:5.1.19.RELEASE]
        at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) [undertow-servlet-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376) [undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830) [undertow-core-2.0.32.Final.jar!/:2.0.32.Final]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_202]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_202]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_202]

當然,筆者的同事也嘗試用Oracle JDK1.8u202在centos7.9中制作Docker Image文件,同樣也是少文件,只是報錯的路徑不一樣。

經過筆者進入docker嘗試,openjdk8u322是在debian11.2上面制作完成的(這里要求了解linux的辨別方法)

 

 解決方法

筆者探索解決方法的過程如下:

首先進入docker鏡像,發現文件/usr/local/openjdk-8/lib/amd64/libawt_xawt.so:是存在的。而后面的libXext.so.6則不存在。

 

 筆者在docker中執行以下命令

whereis libXext.so.6

並沒發現(截至寫博文時已經修復,不再截圖)

后來根據筆者的操作系統知識,看上面的報錯,應該是libawt_xawt.so缺少libXext.so.6的依賴。

在docker中執行以下命令,發現awt依賴的如下(類似下面,筆者已經安裝了libXrender.so情況下執行該命令,如果沒安裝,會有很多顯示not found)

root@0bde6b347fbd:/# ldd /usr/local/openjdk-8/lib/amd64/libawt_xawt.so
/bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
        linux-vdso.so.1 (0x00007fffcffcb000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fbf32914000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbf327d0000)
        libawt.so => /usr/local/openjdk-8/lib/amd64/libawt.so (0x00007fbf324fc000)
        libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007fbf324e7000)
        libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007fbf323a4000)
        libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007fbf3219a000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fbf32192000)
        libXtst.so.6 => not found
        libXi.so.6 => not found
        libjava.so => /usr/local/openjdk-8/lib/amd64/libjava.so (0x00007fbf31f68000)
        libjvm.so => /usr/local/openjdk-8/lib/amd64/server/libjvm.so (0x00007fbf30f51000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbf30d8c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fbf32ba0000)
        libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007fbf30d5f000)
        libverify.so => /usr/local/openjdk-8/lib/amd64/libverify.so (0x00007fbf30b4f000)
        libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007fbf30b4a000)
        libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007fbf30944000)
        libbsd.so.0 => /usr/lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fbf3092d000)
        libmd.so.0 => /usr/lib/x86_64-linux-gnu/libmd.so.0 (0x00007fbf3091e000)

筆者在docker中執行以下命令,查詢相關依賴

sed -i "s@http://deb.debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list
sed -i "s@http://security.debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list
apt update
apt-cache search libxext

 

 

 你只需安裝 libxext6即可,即執行以下命令

apt-get install libxext6

但是為了兼容不同版本的openjdk8(不同版本的debian查詢得到的libxext可能不一樣,比如libxext5,libxext4),筆者選擇使用以下命令

apt-get install libxext*

當然,也會額外下載其他東西,看你的需要吧。

經過多次測試,筆者得到以下的Dockerfile配置

FROM openjdk:8u322-jre
.....
RUN sed -i "s@http://deb.debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
    && sed -i "s@http://security.debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list
RUN apt update
RUN apt-get install libxext* libxrender1* libxtst*  -y
....

按照以上配置后,再次用poi導出excel不再報錯,再來執行命令看看libawt_xawt.so依賴

ldd /usr/local/openjdk-8/lib/amd64/libawt_xawt.so

 

 

如果你是自己制作鏡像,比如使用centos7.9,執行以下命令

sudo yum install libXext* libXrender* libXtst* -y

有人問,為什么,我在宿主機里面安裝oracle jdk/jre,openjdk/jre很少遇到問題?

答:因為制作docker鏡像時,關於操作系統依賴都是最低依賴庫,以便方便發現(Image體積小90-200M左右,否則數GB怎么發行)。

       一般宿主機安裝linux都會安裝libX11或者xorg,即桌面相關,所以不會,會順便安裝上面的依賴庫,所以不會報錯。

      或者因為安裝其他庫(liboffice,imageMagick,vnc筆者猜想的),順便安裝了xorg,libx11。

java awt中含有圖像圖形相關的方法/函數,所以需要很多so動態庫,而我們使用的POI很可能依賴圖像運算相關庫,所以報錯了。
時間太晚,筆者沒去研究 
libxext libxrender libxtst,感興趣的你可以自己搜索了解一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM