linux环境下Java程序UI显示问题
问题形容
我的项目在linux环境下运行时,因为历史遗留起因,须要通过UI界面展现一个二维码供扫码应用。最常见的就是和UI相干的各种谬误了,比方上面这个:
Can't connect to X11 window server using ':2.0' as the value of the DISPLAY variable.
上面咱们通过一个简略的示例来探索一下linux下和UI相干各种谬误及其起因。
简略的样例程序
package my;public class Test{ public static void main(String[] args){ System.out.println("java.awt.headless=\t" + System.getProperty("java.awt.headless")); System.out.println("DISPLAY=\t" + System.getenv("DISPLAY")); JOptionPane.showMessageDialog(null, "Hello!"); }}
能够应用你相熟的任意工具将下面代码编译、并打包为一个JAR包,假如文件名为test.jar
将test.jar上传到linux服务器特定目录下,假如寄存到/opt目录;
通过SSH客户端登录linux
运行程序:$ java -cp test.jar my.Test
零碎输入如下:
java.awt.headless= nullDISPLAY= nullException in thread "main" java.awt.HeadlessException:No X11 DISPLAY variable was set, but this program performed an operation which requires it. at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204) at java.awt.Window.<init>(Window.java:536)
咱们看到,通过SSH登录linux零碎时,以后会话缺省是没有设置DISPLAY环境变量的;而Java应用程序要展现界面须要DISPLAY环境变量指向可用的显示环境(即X11Server地址)
headless属性的作用
如果咱们运行前,将java.awt.headless零碎属性设置为true,后果是什么呢?
运行程序:$ java -Djava.awt.headless=true -cp test.jar my.Test
零碎输入如下:
java.awt.headless= trueDISPLAY= nullException in thread "main" java.awt.HeadlessException at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204) at java.awt.Window.<init>(Window.java:536)
设置headless并不能解决UI显示问题;它更像是一种提醒,告知以后零碎无奈应用图形环境;
启动第三方XServer服务
咱们尝试在Windows环境下启动XServer服务:windows下局部linux近程工具通过内嵌XServer服务反对拜访linux图形界面,比方:XShell、MobaXTerm、XMing、X-Win32等;
咱们这里应用一个收费的更纯正的XServer windows服务程序:VcXsrv
下载地址
启动VcXsrv当前(留神放开拜访权限,配置时抉择:disable access control
),windows状态栏会多出一个VcXsrv的任务栏图标,鼠标悬停在下面,会提醒以后XServer的拜访地址,比方xxx:0.0
其中,冒号前是主机地址,域名或ip;冒号后的第一个数字代表XServer监听端口,这个数字 + 6000 即是真正的监听端口;
在windows命令行执行C:\> netstat -ano | find "600"
,显示如下;
TCP 0.0.0.0:6000 0.0.0.0:0 LISTENING 32472TCP 127.0.0.1:6000 127.0.0.1:53790 ESTABLISHED 32472TCP 127.0.0.1:6000 127.0.0.1:53791 ESTABLISHED 32472TCP 127.0.0.1:6000 127.0.0.1:53792 ESTABLISHED 32472TCP 127.0.0.1:53790 127.0.0.1:6000 ESTABLISHED 32472TCP 127.0.0.1:53791 127.0.0.1:6000 ESTABLISHED 32472TCP 127.0.0.1:53792 127.0.0.1:6000 ESTABLISHED 32472TCP [::]:6000 [::]:0 LISTENING 32472
咱们看到本地监听的TCP端口 6000 ,这正是XServer过程关上的;如果咱们在启动VcXsrv时,端口设定为 -1
,则示意由VcXsrv,从6000开始探测第一个可用的端口;
DISPLAY环境变量指向近程XServer地址
咱们尝试在运行java程序前,指定DISPLAY环境变量如下:
# 10.1.27.33替换为windows主机地址,:0替换为Xserver监听端口减去6000的值$ export DISPLAY=10.1.27.33:0$ java -cp test.jar my.Test
运行程序,这时候咱们发现没有谬误了!只是咱们的界面在哪儿呢?别慌!看下windows任务栏,你将在以后windows桌面上发现linux过程的图形界面输入。
和远程桌面技术显示近程图形界面不同(传递压缩的位图);XServer和XClient(也就是须要输入图形界面的linux过程)之间通过X协定交谈(传递绘图指令),所以传输数据量更小,对网络带宽的需要低。
DISPLAY环境变量指向本地XServer地址
首先咱们启动并登录一个装置了图形界面的linux服务器。使零碎为咱们筹备好本地图形环境。
而后,近程应用SSH,近程登录服务器。应用$ who
命令来查看,以后可用的图形环境
test :0 2022-04-14 09:47 (:0)root pts/0 2022-04-14 09:47 (10.1.27.33)
留神,冒号前为空,示意linux本地的图形环境。咱们设置以后SSH连贯的DISPLAY属性指向linux本地图形环境。
$ export DISPLAY=":0"
应用$ xhost
命令可查看Xserver的受权。
access control enabled, only authorized clients can connectSI:localuser:rootSI:localuser:test
咱们凋谢所有用户可连贯:$ xhost +
access control disabled, clients can connect from any host
接下来,从新运行java程序:
$ export DISPLAY=":0"$ xhost +$ cd /opt$ java -cp test.jar my.Test
这时候,察看linux本地登录用户的桌面,发现通过SSH运行的Java程序的界面被投射到linux本地用户桌面了。
无奈连贯DISPLAY的谬误
如果DISPLAY设定值和以后可用的图形环境不统一,那么就会产生相似上面的谬误。(我的项目在应用VNC登录时偶发上面谬误)
Can't connect to X11 window server using ':2.0' as the value of the DISPLAY variable.
参考文档
- Linux图形系统框架 与 X协定
- 对于VNC的管制原理以及装置应用办法