SSH使用X11转发引起的异常
一、问题背景
测试同学在测试导出Excel功能时报错,异常日志如下:
java.util.concurrent.ExecutionException: java.awt.AWTError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable.
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at com.xuanwu.ds.service.impl.export.async.ExportWorker.run(ExportWorker.java:76)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.awt.AWTError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
at sun.awt.X11FontManager.isHeadless(X11FontManager.java:509)
at sun.awt.X11FontManager.getFileNameFromPlatformName(X11FontManager.java:189)
at sun.font.SunFontManager.initCompositeFonts(SunFontManager.java:3481)
at sun.font.SunFontManager.access$700(SunFontManager.java:65)
at sun.font.SunFontManager$2.run(SunFontManager.java:545)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.SunFontManager.<init>(SunFontManager.java:376)
at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
at java.security.AccessController.doPrivileged(Native Method)
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
at java.awt.Font.getFont2D(Font.java:491)
at java.awt.Font.canDisplayUpTo(Font.java:2060)
at java.awt.font.TextLayout.singleFont(TextLayout.java:470)
at java.awt.font.TextLayout.<init>(TextLayout.java:531)
at org.apache.poi.ss.util.SheetUtil.getDefaultCharWidth(SheetUtil.java:275)
at org.apache.poi.xssf.streaming.AutoSizeColumnTracker.<init>(AutoSizeColumnTracker.java:117)
at org.apache.poi.xssf.streaming.SXSSFSheet.<init>(SXSSFSheet.java:82)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createAndRegisterSXSSFSheet(SXSSFWorkbook.java:658)
at org.apache.poi.xssf.streaming.SXSSFWorkbook.createSheet(SXSSFWorkbook.java:650)
// 此处省略部分业务堆栈信息
... 3 more
但是在开发环境(Windows),该导出功能正常。
二、原因分析
根据异常堆栈信息,无法连接到X11 window server。
2.1 X Window System简介
The X Window System (also known as X11, or just X) is a software package and network protocol that lets you interact locally, using your personal computer’s display, mouse, and keyboard, with the graphical user interface (GUI) of an application running on a remote networked computer.
X Window System(也称为 X11,或简称 X)是一个软件包和网络协议,可让您使用个人计算机的显示器、鼠标和键盘进行本地交互,同时运行应用程序的图形用户界面 (GUI) 在远程联网计算机上。
You can use X forwarding in an SSH session on your personal computer to securely run graphical applications (X clients) installed on the Indiana University research supercomputers.
您可以在个人计算机上的 SSH 会话中使用 X (X Window System) 转发来安全地运行安装在印第安纳大学研究超级计算机上的图形应用程序(X 客户端)。
For X forwarding in SSH to work, your personal computer must be running an X server program. The X server program manages the interaction between the remote application (the X client) and your computer’s hardware.
要在 SSH 中进行 X 转发,您的个人计算机必须运行 X 服务器程序。 X 服务器程序管理远程应用程序(X 客户端)和计算机硬件之间的交互
2.2 SSH使用X转发
SSH使用X转发参照一下命令:
Linux: ssh -X username@hostname
macOS: ssh -Y username@hostname
SSH使用X转发所需要具备的环境详见:Use X forwarding on a personal computer
2.3 日志分析
根据上述异常日志信息,推测由于使用SSH连接到服务器开启了X11转发,Java应用程序作为X Client连接到 X Server,目前报错应该是SSH连接断开后X11连接失败导致。
与测试同学沟通,发现使用Xshell工具连接到服务器启动的Java进程,网上也有文章描述Xshell存在该问题,所以判断是使用Xshel启动Java进程后XShell断开连接导致出现了该问题。
2.4 复现异常
使用Xshell连接到服务器后启动Java进程后,关闭Xshell中的SSH连接,进行导出操作,错误复现。
查看Xshell中SSH连接的配置,默认开启了X11转发,配置如下:
三、解决方案
(1) 如果使用XShell,则关闭X11转发
(2) 设置JVM参数,不去检查图形界面
-Djava.awt.headless=true
四、总结
由于XShell工具中的SSH连接默认开启X11转发,Java进程启动后,关闭了SSH连接,X11连接失败从而出现上述问题。解决方案:
- 使用XShell时关闭X11转发
- JVM启动参数配置:
-Djava.awt.headless=true
- 使用XShell开启了X11转发,请保持SSH连接不要断开