问题
I noticed that Java proposes different look and feel classes for root and non-root users. I am trying to understand how to make LAF consistent. Moreover, it's inconsistent even within a user/root: depends on how user/root logged in:
Sample code (compiled and packaged in 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) {
}
}
}
Scenario 1 Logs in to machine (in GUI mode) as a regular user
Sample output (as user)
[xxx@yyy Downloads]$ java -classpath laf.jar laf
com.sun.java.swing.plaf.gtk.GTKLookAndFeel
Sample output (switch to root via su
)
[root@yyy Downloads]# java -classpath ./laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel
Scenario 2 Logs in to machine (in GUI mode) as root
Sample output (as root)
[root@yyy Downloads]# java -classpath ./laf.jar laf
com.sun.java.swing.plaf.gtk.GTKLookAndFeel
Scenario 3 Logs in to machine via SSH as a regular user (similar as scenario #1 above, but in this case - same LAF)
Sample output (as user)
[xxx@yyy Downloads]$ java -classpath laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel
Sample output (switch to root)
[root@yyy Downloads]# java -classpath ./laf.jar laf
javax.swing.plaf.metal.MetalLookAndFeel
Software versions:
[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)
回答1:
The first line of getSystemLookAndFeelClassName
is:
public static String getSystemLookAndFeelClassName() {
String systemLAF = AccessController.doPrivileged(
new GetPropertyAction("swing.systemlaf"));
So you can use the JAVA_OPTS of the user to set
-Dswing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel
As default.
add this to the .rc
-File of the user:
set JAVA_OPTS=-Dswing.systemlaf=javax.swing.plaf.metal.MetalLookAndFeel
export JAVA_OPTS
Regards
回答2:
This is less about root, and more about environment variables.
Basically, the UIManager.getSystemLookAndFeelClassName method works like this:
- Check the
swing.systemlaf
system property. This allows the user to override whatever the system wants to choose. If it is not null, it's used. - Otherwise, if the operating system is Windows, it returns the
WindowsLookAndFeel
. - Otherwise, it checks the
sun.desktop
property. Ifsun.desktop
is set tognome
, and GTK is available natively, it returs theGTKLookAndFeel
- Otherwise, checks for Mac OS X and Solaris and returns appropriate values for these operating systems.
- If all other checks failed, it returns the "cross platform" L&F, which is
MetalLookAndFeel
.
So, the part that is relevant to Linux/Unix is the part that checks sun.desktop
. This property is set when the JVM starts up. It is set to gnome
if the environment variable GNOME_DESKTOP_SESSION_ID
exists, ignoring its contents, and it is set to null otherwise. I believe this is the pertinent native source code that does this.
So, on Linux, if that environment variable is set (and GTK is available), your L&F will be set to GTKLookAndFeel
. If not, it will be set to MetalLookAndFeel
.
When you log in to a Gnome-based Linux using the desktop manager, your environment will have that variable set. But the su
command does not propagate environment variables by default. Thus, when you su to any user, not necessarily root, you lose the GNOME_DESKTOP_SESSION_ID
environment variable, and Java will default to MetalLookAndFeel
.
You can cause your environment to be passed through su
by using su -p
, or if you are using sudo
, using sudo -E
.
The ssh
command, like su
and sudo
, does not propagate environment variables. This can also be worked around using ~/.ssh/environment
.
However, as already stated - you can easily force a specific L&F by passing the -Dswing.systemlaf=...
switch to the java command.
来源:https://stackoverflow.com/questions/33735981/java-in-linux-different-look-and-feel-classes-for-root-and-non-root