【问题标题】:Java in Linux - different look and feel classes for root and non-rootLinux 中的 Java - root 和非 root 的不同外观类
【发布时间】:2015-11-16 12:58:23
【问题描述】:

我注意到 Java 为 root 用户和非 root 用户提供了不同的外观类。我试图了解如何使 LAF 保持一致。此外,即使在用户/root 中也是不一致的:取决于用户/root 的登录方式:

示例代码(编译打包在laf.jar):

import javax.swing.UIManager;

public class laf {
    public static void main(java.lang.String[] args) {
        try {
            System.out.print(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
        }
    }
}

场景 1 以普通用户身份登录机器(在 GUI 模式下)

示例输出(作为用户

[xxx@yyy Downloads]$ java -classpath laf.jar laf
com.sun.java.swing.plaf.gtk.GTKLookAndFeel

示例输出(通过su切换到root

[root@yyy Downloads]# java -classpath ./laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel

场景 2 以 root 身份登录机器(在 GUI 模式下)

示例输出(作为 root

[root@yyy Downloads]# java -classpath ./laf.jar laf
com.sun.java.swing.plaf.gtk.GTKLookAndFeel

场景 3 以普通用户身份通过​​ SSH 登录机器(类似于上面的场景 #1,但在本例中 - 相同的 LAF)

示例输出(作为用户

[xxx@yyy Downloads]$ java -classpath laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel

示例输出(切换到 root

[root@yyy Downloads]# java -classpath ./laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel

软件版本:

[root@yyy Downloads]# java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build pxa6470sr9fp10-20150708_01(SR9 FP10))
IBM J9 VM (build 2.6, JRE 1.7.0 Linux amd64-64 Compressed References     20150701_255667 (JIT enabled, AOT enabled)
J9VM - R26_Java726_SR9_20150701_0050_B255667
JIT  - tr.r11_20150626_95120.01
GC   - R26_Java726_SR9_20150701_0050_B255667_CMPRSS
J9CL - 20150701_255667)
JCL - 20150628_01 based on Oracle jdk7u85-b15

[root@yyy Downloads]# cat /etc/redhat-release 
Red Hat Enterprise Linux Workstation release 6.7 (Santiago)

【问题讨论】:

  • 这可能来自于用户环境的不同;试试看env在不同场景下的结果,或者在Java中,使用System.getenv()的结果。
  • 您能否在各种设置中检查您的环境中是否有变量GNOME_DESKTOP_SESSION_ID
  • 1) 作为用户它说“this-is-depriated” 2) 在“su -”作为 root 之后它给出了空白输出
  • 如果您想要一致的跨平台外观,您可能需要坚持使用Nimbus themeUIManager.getCrossPlatformLookAndFeelClassName()
  • Nimbus 是为了更好看的跨平台 L&F 而创建的,但无论出于何种原因,它从未更新为默认值。

标签: java linux redhat look-and-feel


【解决方案1】:

这不是关于 root,而是更多关于环境变量。

基本上,UIManager.getSystemLookAndFeelClassName 方法是这样工作的:

  • 检查swing.systemlaf 系统属性。这允许用户覆盖系统想要选择的任何内容。如果不为 null,则使用它。
  • 否则,如果操作系统是 Windows,则返回 WindowsLookAndFeel
  • 否则,它会检查sun.desktop 属性。如果 sun.desktop 设置为 gnome,并且 GTK 本身可用,则返回 GTKLookAndFeel
  • 否则,检查 Mac OS X 和 Solaris 并为这些操作系统返回适当的值。
  • 如果所有其他检查均失败,则返回“跨平台”L&F,即MetalLookAndFeel

因此,与 Linux/Unix 相关的部分是检查 sun.desktop 的部分。此属性在 JVM 启动时设置。如果环境变量GNOME_DESKTOP_SESSION_ID 存在,则设置为gnome,忽略其内容,否则设置为null。我相信this is the pertinent native source code 会这样做。

因此,在 Linux 上,如果设置了该环境变量(并且 GTK 可用),您的 L&F 将设置为 GTKLookAndFeel。如果没有,它将被设置为MetalLookAndFeel

当您使用桌面管理器登录到基于 Gnome 的 Linux 时,您的环境将设置该变量。但是su 命令默认不传播环境变量。因此,当您 su 到任何用户(不一定是 root)时,您会丢失 GNOME_DESKTOP_SESSION_ID 环境变量,Java 将默认为 MetalLookAndFeel

您可以使用su -p 使您的环境通过su,或者如果您正在使用sudo,则使用sudo -E

ssh 命令与susudo 一样,不会传播环境变量。这也可以使用~/.ssh/environment 解决。

但是,如前所述 - 您可以通过将 -Dswing.systemlaf=... 开关传递给 java 命令轻松地强制执行特定的 L&F。

【讨论】:

  • 感谢您的解释,正如我在上面所说的 GNOME_DESKTOP_SESSION_ID 没有包含任何有意义的内容。我的选择是通过 -D 明确定义 LAF
  • 顺便说一句,在 Ubuntu OS 12.04.02 上也观察到了这个问题。令人惊讶的是,在 Ubuntu 上,我得到完全相同的结果:作为用户,它说 echo echo $GNOME_DESKTOP_SESSION_ID => "this-is-depriated",作为 root - 空白输出,以及作为用户和 root 的不同 LAF。
  • @BaratSahdzijeu 它不必包含任何有意义的。它必须存在才能选择 GTK L&F。是的,Ubuntu 是基于 Gnome 的 Linux。
  • 这有助于解释问题,但不能提供与桌面行为相匹配的可扩展解决方案。例如,如果安装程序之后想在用户空间启动一个 Java 进程,如何在不强制用户提供对安装程序中调用的sudo 命令的开关的情况下获取用户的环境变量?对于一个特定的安装程序,sudo -u 命令用于在用户空间启动进程,因此环境变量被sudo 隐藏了两次。安装程序如何适应这种情况?
  • 怎么会有人在 OpenJDK 源代码树中找到任何东西,嘀咕,嘀咕?尽管 GNOME_DESKTOP_SESSION_ID 自 2008 年以来已被弃用 (bugzilla.gnome.org/show_bug.cgi?id=542880),但代码仍然存在于 hg.openjdk.java.net/jdk9/jdk9/jdk/file/tip/src/java.base/unix/… 中。 Gnome 仍然设置它,大概要感谢该错误的修复 - “不推荐使用” - 那么我为什么要获得 Metal LAF?因为我是从我在 gnome-session 之前启动的 xterm 启动 Java 的,以防万一。非常有意义,感谢@RealSkeptic。
【解决方案2】:

getSystemLookAndFeelClassName的第一行是:

public static String getSystemLookAndFeelClassName() {
    String systemLAF = AccessController.doPrivileged(
                         new GetPropertyAction("swing.systemlaf"));

所以可以使用用户的JAVA_OPTS来设置

-Dswing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel

默认。

将此添加到用户的.rc-File:

set JAVA_OPTS=-Dswing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel
export JAVA_OPTS

问候

【讨论】:

  • 当然,我会尝试使用属性,但我很惊讶它不是开箱即用的。
  • 在用户级别(bashrc 或配置文件)进行修改不是一种选择,因为我们无法控制它,也不希望我们的应用程序影响系统。所以,我的解决方案是在应用程序的启动脚本中添加一个片段“-Dswing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel”
  • 记下 com.sun.javax.swing.plaf.metal.CrossPlatformLookAndFeel 在我使用的 IBM JRE 中不可用。所以它不是一个跨平台的解决方案。我仍然建议使用我在之前评论中提到的内容:javax.swing.plaf.metal.MetalLookAndFeel
猜你喜欢
  • 1970-01-01
  • 2016-04-11
  • 2023-03-03
  • 2023-03-03
  • 1970-01-01
  • 2018-01-13
  • 1970-01-01
  • 2017-07-03
  • 2013-04-13
相关资源
最近更新 更多