Bug 264356 - java/openjdk17: getLocalGraphicsEnvironment() on for multi-screen setups throws exception: Cannot read the array length because "this.screens" is null
Summary: java/openjdk17: getLocalGraphicsEnvironment() on for multi-screen setups thro...
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Some People
Assignee: Greg Lewis
URL:
Keywords: needs-qa
Depends on:
Blocks:
 
Reported: 2022-05-30 20:45 UTC by Sean Farley
Modified: 2022-08-03 04:38 UTC (History)
1 user (show)

See Also:
bugzilla: maintainer-feedback? (java)
koobs: merge-quarterly?


Attachments
Fix for screen count (612 bytes, text/plain)
2022-05-30 20:45 UTC, Sean Farley
no flags Details
Program demonstrating exception (178 bytes, text/plain)
2022-05-30 20:46 UTC, Sean Farley
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sean Farley freebsd_committer freebsd_triage 2022-05-30 20:45:32 UTC
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)
Comment 1 Sean Farley freebsd_committer freebsd_triage 2022-05-30 20:46:06 UTC
Created attachment 234336 [details]
Program demonstrating exception
Comment 2 Greg Lewis freebsd_committer freebsd_triage 2022-05-30 21:55:06 UTC
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.
Comment 3 Sean Farley freebsd_committer freebsd_triage 2022-05-30 23:50:55 UTC
(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.
Comment 4 commit-hook freebsd_committer freebsd_triage 2022-05-31 00:45:17 UTC
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(+)
Comment 5 Greg Lewis freebsd_committer freebsd_triage 2022-05-31 05:39:03 UTC
Note to self: openjdk18 needs this too
Comment 6 Greg Lewis freebsd_committer freebsd_triage 2022-05-31 05:44:49 UTC
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.
Comment 7 Greg Lewis freebsd_committer freebsd_triage 2022-08-03 04:38:40 UTC
openjdk18 has now been fixed as part of the 18.0.2 update