• 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,感兴趣的你可以自己搜索了解一下。

  • 相关阅读:
    Cookie
    servletContext组件
    Servlet的定义及生命周期
    导引:servlet&Jsp的经典模式
    一个servlet server,由移植自Tomcat的连接器模块和自编写的container模块代码组成
    一个servlet web server,由移植自Tomcat的完整的connector模块和简化的Container(取代servlet处理器)组成
    python初识
    Maekdown光速习得
    实例学习——爬取简书网用户动态
    使用CSDN-markdown编辑器粘贴代码块时崩溃问题解决
  • 原文地址:https://www.cnblogs.com/passedbylove/p/15966156.html
Copyright © 2020-2023  润新知