关于java:linux环境下Java程序UI显示问题

46次阅读

共计 3223 个字符,预计需要花费 9 分钟才能阅读完成。

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=      null
DISPLAY=        null
Exception 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=      true
DISPLAY=        null
Exception 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       32472
TCP    127.0.0.1:6000         127.0.0.1:53790        ESTABLISHED     32472
TCP    127.0.0.1:6000         127.0.0.1:53791        ESTABLISHED     32472
TCP    127.0.0.1:6000         127.0.0.1:53792        ESTABLISHED     32472
TCP    127.0.0.1:53790        127.0.0.1:6000         ESTABLISHED     32472
TCP    127.0.0.1:53791        127.0.0.1:6000         ESTABLISHED     32472
TCP    127.0.0.1:53792        127.0.0.1:6000         ESTABLISHED     32472
TCP    [::]: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 connect
SI:localuser:root
SI: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 的管制原理以及装置应用办法

正文完
 0