当前位置: 首页 > Linux

Java程序在linux环境下UI显示问题

时间:2023-04-06 21:45:27 Linux

Java程序在linux环境下UI显示问题问题描述项目在linux环境下运行时,由于历史原因,需要通过UI界面显示一个二维码进行扫描。最常见的是与UI相关的各种错误,例如:无法使用“:2.0”作为DISPLAY变量的值连接到X11窗口服务器。让我们用一个简单的例子来探究一下Linux下与UI相关的各种错误及其原因。简单示例程序包my;publicclassTest{publicstaticvoidmain(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,"你好!");}}你可以使用任何你熟悉的工具来替换上面的代码编译打包成JAR包,假设文件名为test.jar,上传test.jar到linux服务器的特定目录,假设它存放在/opt目录下;通过SSH客户端登录linux运行程序:$java-cptest.jarmy.Test系统输出如下:java.awt.headless=nullDISPLAY=nullExceptioninthread"main"java.awt.HeadlessException:NoX11DISPLAY变量已设置,但此程序执行了需要它的操作。atjava.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)atjava.awt.Window.(Window.java:536)我们看到通过SSH登录linux系统时,当前会话没有默认设置DISPLAY环境变量;但是Java应用程序需要显示界面,DISPLAY环境变量指向可用的显示环境(即X11Server地址)。无头属性的功能。ess系统属性设置为true,结果是什么?运行程序:$java-Djava.awt.headless=true-cptest.jarmy.Test系统输出如下:java.awt.headless=trueDISPLAY=nullExceptioninthread"main"java.awt.HeadlessExceptionatjava.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)atjava.awt.Window.(Window.java:536)设置headless并不能解决UI显示问题;它更像是一个提醒,当前系统不能使用图形环境;启动第三方XServer服务我们尝试在Windows环境下启动XServer服务:windows下的一些linux远程工具支持通过内嵌的XServer服务访问linux图形界面,如:XShell、MobaXTerm、XMing、X-Win32,ETC。;这里我们使用一个免费更纯的XServerwindows服务程序:VcXsrv下载地址启动VcXsrv后(注意释放访问权限,配置时选择:disableaccesscontrol),windows状态下会多一个VcXsrv的任务栏图标bar,悬停在上面,会提示当前XServer的访问地址,比如xxx:0.0其中,冒号前是主机地址、域名或ip;冒号后的第一个数字代表XServer的监听端口,这个数字+6000才是真正的监听端口;在windows中执行C:\>netstat-ano|在命令行中找到“600”,显示如下;127.0.0.1:53791建立了32472TCP127.0.0.0.0.1:6000127.0.0.0.0.1:53792建立了32472TCP127.0.0.0.0.0.1.1:53790127.0.0.0.1:6000建立了32472TCP127.0.0.0.0.0.0.0.0.0.0.0.0.0.10.0.0.bhister0.1:6000ESTABLISHED32472TCP[::]:6000[::]:0LISTENING32472我们看到本地监听的TCP端口6000,正是XServer进程开启的;如果我们启动VcXsrv,端口设置为-1,这意味着VcXsrv开始检测从6000开始的第一个可用端口;DISPLAY环境变量指向远程XServer地址。我们尝试在运行java程序之前指定DISPLAY环境变量如下:#10.1.27.33替换为windows主机地址,:0替换为Xserver监听端口减去6000的值$exportDISPLAY=10.1.27.33:0$java-cptest.jarmy.Test运行程序,发现没有报错!我们的接口在哪里?不要恐慌!查看windows任务栏,会发现linux进程的GUI输出与远程桌面技术在当前windows桌面上显示的不一样(通过压缩位图);XServer和XClient(即需要输出GUI的linux进程)通过X协议(传输绘图指令)进行通信,因此传输的数据量较小,对网络带宽的需求较低。DISPLAY环境变量指向本地XServer地址。首先,我们启动并登录一台安装了图形界面的Linux服务器。让系统为我们准备好本地图形环境。然后,使用SSH远程登录服务器。使用$who命令查看当前可用的图形环境test:02022-04-1409:47(:0)rootpts/02022-04-1409:47(10.1.27.33)注意冒号为空,表示Linux本地图形环境。我们将当前SSH连接的DISPLAY属性设置为指向Linux本地图形环境。$exportDISPLAY=":0"使用$xhost命令查看Xserver的权限。启用访问控制,只有授权的客户端才能连接SI:localuser:rootSI:localuser:test我们打开所有用户连接:$xhost+accesscontroldisabled,客户端可以从任何主机连接接下来,重新运行java程序:$exportDISPLAY=":0"$xhost+$cd/opt$java-cptest.jarmy.Test此时观察本地Linux登录用户的桌面,发现通过SSH运行的Java程序的界面投影到本地Linux用户的桌面。无法连接DISPLAY的错误如果DISPLAY设置值与当前可用的图形环境不一致,会出现类似如下的错误。例如连接后使用suusername切换用户身份时,由于XServer默认只授权给初始登录用户,切换用户身份后,新用户的DISPLAY环境变量会失效(指向的图形环境缺少权限)。另外,项目使用VNC登录时,偶尔会出现如下错误:Can'tconnecttoX11windowserverusing':2.0'asthevalueoftheDISPLAYvariable。在某些场景下使用SSH转发X11协议数据,如果linux服务器只开启了少量本地TCP端口(比如开启SSH的22端口),如果不能直接连接到外部的XServer服务器,你可以通过SSH代理通过SSH转发X11协议。这时我们需要在linux服务器上开启SSHD服务的X协议转发功能;修改:/etc/ssh/sshd_config文件,开启X11协议转发开关。X11Forwardingyes在远程SSH客户端连接中启用X11协议转发支持。以putty为例,打开putty配置:ConnectionSSHX11选择EnableX11forwarding,在XDISPLAY位置填写本地XServer地址,例如:localhost:0.0此时我们使用putty打开SSH连接,查看当前连接DISPLAY设置:$echo$DISPLAY我们会发现DISPLAY环境变量的值设置为:10.1.27.70:10.0,其中10.1.27.70是linux主机的ip,10.0是linux上的XServer服务地址通过SSHD服务虚拟化的主机(当然只是转发)这样,图形数据的传输方式为:linux主机图形程序<---X11协议:端口6010--->linux主机上的SSHD虚拟XServer<---SSH协议:22端口--->windows远程SSH客户端<---X11协议:6000端口--->windowsXserver服务器参考文档Linux图形系统框架和X协议关于VNC的控制原理和安装方法并使用它