Created attachment 234335 [details] Fix for screen count Starting in OpenJDK 17 (tested on FreeBSD), a call to java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment() will cause a program to throw java.lang.ExceptionInInitializerError if run on a screen that is not the first screen, i.e., :3.0. I am unsure how good the attached fix is, but it does prevent the crash. Basically, the variable screens is null when run on another screen such as :3.1. As the only thing needed is the number of screens, I switched it to use the already defined numScreens. It is easy to duplicate using xephyr: Xephyr :3 -screen 800x600 -screen 800x600 Running the attached java program on screen :3.0 will work. Running it on screen :3.1 throws an exception: Exception in thread "main" java.lang.ExceptionInInitializerError at java.desktop/java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:106) at GraphEnv.main(GraphEnv.java:18) Caused by: java.lang.NullPointerException: Cannot read the array length because "this.screens" is null at java.desktop/sun.awt.X11GraphicsEnvironment.initDevices(X11GraphicsEnvironment.java:235) at java.desktop/sun.awt.X11GraphicsEnvironment.rebuildDevices(X11GraphicsEnvironment.java:216) at java.desktop/sun.awt.X11GraphicsEnvironment.<init>(X11GraphicsEnvironment.java:201) at java.desktop/sun.awt.PlatformGraphicsInfo.createGE(PlatformGraphicsInfo.java:36) at java.desktop/java.awt.GraphicsEnvironment$LocalGE.createGE(GraphicsEnvironment.java:93) at java.desktop/java.awt.GraphicsEnvironment$LocalGE.<clinit>(GraphicsEnvironment.java:84) at java.desktop/java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:106) at GraphEnv.main(GraphEnv.java:18) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419) at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192) at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
Created attachment 234336 [details] Program demonstrating exception
Thanks Sean. I think the fix you propose is reasonable. The problem with using the screens array here is that is initialised in a method in the base class that is overridden here. So it never gets initialised and is null.
(In reply to Greg Lewis from comment #2) You are welcome. I noticed on your blog that you had run into this issue too. I have not touched Java in a loooooong time, so I am happy that I found a decent solution. :) I got a bit lost when looking at the code, so I need to ask why does it not end up null on a :N.0 screen? I think/thought it had something to do with how the DISPLAY variable was parsed.
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/ports/commit/?id=0de164bdb551505ac86059866d855a8035de983f commit 0de164bdb551505ac86059866d855a8035de983f Author: Sean Farley <scf@FreeBSD.org> AuthorDate: 2022-05-31 00:37:59 +0000 Commit: Greg Lewis <glewis@FreeBSD.org> CommitDate: 2022-05-31 00:42:52 +0000 java/openjdk17: Fix an NPE when using a multi-screen X11 setup PR: 264356 Reported by: scf@ ...top_unix_classes_sun_awt_X11GraphicsEnvironment.java (new) | 11 +++++++++++ 1 file changed, 11 insertions(+)
Note to self: openjdk18 needs this too
The `screens` array is always null, so any time the second part of the boolean expression in ``` mainScreen = 0 < index && index < screens.length ? index : 0; ``` is evaluated you'll get an NPE. However, since index (the default screen number) is 0 in most cases the first part of the conditional is false and nothing happens.
openjdk18 has now been fixed as part of the 18.0.2 update