I have a java app that the user might invoke from the command line by running java -jar app.jar or from a desktop environment by double-clicking the .jar file.
I would like the app to be able to detect if it can safely launch a Swing GUI or if it has to use a command-line interface. If I just start calling Swing functions without checking for the availability of a window system, Java bails out with an InternalError.
For instance, if I unset DISPLAY and run the application, I get:
java.lang.InternalError: Can't connect to X11 window server using '' as the value of the DISPLAY variable. at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method) at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:62) at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:178) at java.security.AccessController.doPrivileged(Native Method) at sun.awt.X11GraphicsEnvironment.(X11GraphicsEnvironment.java:142) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82) at sun.awt.X11.XToolkit.(XToolkit.java:112) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at java.awt.Toolkit$2.run(Toolkit.java:849) at java.security.AccessController.doPrivileged(Native Method) at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:841) [etc]
I could just try...catch the InternalError and run the command-line interface in that case, but I'd heard that one shouldn't catch Errors because they might leave the JVM in an inconsistent state. (Please correct me if I'm wrong.)
Is there any way that I can check to see if I can safely open a Swing window without catching an InternalError? (I could just check if the DISPLAY environment variable is not empty, but a non-empty DISPLAY is no guarantee that the X server actually works. Nor would that approach work in non-X11 environments.)
You can use GraphicsEnvironment.isHeadless()
I could just try...catch the InternalError and run the command-line interface in that case, but I'd heard that one shouldn't catch Errors because they might leave the JVM in an inconsistent state. (Please correct me if I'm wrong.)
Your understanding is half right.
It is a bad idea to catch an Error and attempt to recover / continue running because the JVM could (already) be in a state from which recovery is not possible.
However, catching a specific error, printing an informative diagnostic to the console and immediately exiting the JVM is a pretty safe thing to do. (The System.out / err streams are pretty resilient to most things that cause an Error
being thrown.)
In this particular case, there's probably nothing you could do to recover. So bailing out is the most sensible option anyway. (Calling isHeadless()
before you attempt to start the GUI is a better idea though.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With