RFR: JDK-8304054: Linux: NullPointerException from FontConfiguration.getVersion in case no fonts are installed
Alexey Ivanov
aivanov at openjdk.org
Thu Apr 13 20:13:34 UTC 2023
On Wed, 15 Mar 2023 16:02:36 GMT, Matthias Baesken <mbaesken at openjdk.org> wrote:
> On Linux Alpine we were running in the jtreg awt tests into a lot of NPEs like this :
>
> java.lang.InternalError: java.lang.reflect.InvocationTargetException
> at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:87)
> at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
> at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:75)
> at java.desktop/java.awt.Font.getFont2D(Font.java:526)
> at java.desktop/java.awt.Font$FontAccessImpl.getFont2D(Font.java:265)
> at java.desktop/sun.font.FontUtilities.getFont2D(FontUtilities.java:148)
> at java.desktop/sun.font.GlyphLayout$SDCache.<init>(GlyphLayout.java:254)
> at java.desktop/sun.font.GlyphLayout$SDCache.get(GlyphLayout.java:328)
> at java.desktop/sun.font.GlyphLayout.layout(GlyphLayout.java:375)
> at java.desktop/java.awt.Font.layoutGlyphVector(Font.java:2858)
> at FontLayoutStressTest.doLayout(FontLayoutStressTest.java:51)
> at FontLayoutStressTest.main(FontLayoutStressTest.java:57)
> 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 com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
> at java.base/java.lang.Thread.run(Thread.java:833)
> Caused by: java.lang.reflect.InvocationTargetException
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
> at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
> at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
> at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
> at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:85)
> ... 17 more
> Caused by: java.lang.NullPointerException: Cannot load from short array because "sun.awt.FontConfiguration.head" is null
> at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
> at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:224)
> at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:106)
> at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:706)
> at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:358)
> at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:315)
> at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
> at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:315)
> at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
> at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)
> ... 23 more
>
> Seems this was caused because no fonts were installed on the machine.
> Probably 'head' in FontConfiguration.getVersion() should be checked for null and a specific exception like "Check your fonts or fonts configuration"
> should be throw.
I reproduced this exception on a system where FontConfig library is installed yet no fonts are present.
It looks like Java can't or doesn't create its own `fontconfig.properties` file in such a case, which results in the exception from the PR description. Yet if I pass a dummy `fontconfig.properties` with `-Dsun.awt.fontconfig=/path/fontconfig.properties`, the exception isn't thrown.
For example,
$ fc-list
$ ./jdk-17.0.6/bin/java ListFonts
Exception in thread "main" java.lang.InternalError: java.lang.reflect.InvocationTargetException
at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:87)
...
Caused by: java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.NullPointerException: Cannot load from short array because "sun.awt.FontConfiguration.head" is null
at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1262)
at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:224)
at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:106)
at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:706)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:358)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:315)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:315)
at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:56)
... 13 more
$ ./jdk-21/bin/java ListFonts
Exception in thread "main" java.lang.NullPointerException: Cannot load from short array because "sun.awt.FontConfiguration.head" is null
at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1256)
at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:221)
at java.desktop/sun.awt.FontConfiguration.init(FontConfiguration.java:105)
at java.desktop/sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:696)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:352)
at java.desktop/sun.font.SunFontManager$2.run(SunFontManager.java:309)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
at java.desktop/sun.font.SunFontManager.<init>(SunFontManager.java:309)
at java.desktop/sun.awt.FcFontManager.<init>(FcFontManager.java:35)
at java.desktop/sun.awt.X11FontManager.<init>(X11FontManager.java:55)
at java.desktop/sun.font.PlatformFontInfo.createFontManager(PlatformFontInfo.java:37)
at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:51)
at java.desktop/sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:137)
at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:171)
at java.desktop/sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:195)
at java.desktop/sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:80)
at ListFonts.main(ListFonts.java:8)
With explicit `fontconfig.properties`:
$ ./jdk-17.0.6/bin/java -Dsun.awt.fontconfig=~/fontconfig.properties ListFonts
Dialog
DialogInput
Monospaced
SansSerif
Serif
$ ./jdk-21/bin/java -Dsun.awt.fontconfig=~/fontconfig.properties ListFonts
Dialog
DialogInput
Monospaced
SansSerif
Serif
The sample app `ListFonts.java`:
import java.awt.GraphicsEnvironment;
import java.util.Arrays;
public class ListFonts {
public static void main(String[] args) {
Arrays.stream(GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames())
.forEach(System.out::println);
}
}
The dummy `fontconfig.properties`:
version=1
sequence.allfonts=default
With Matthias's fix, the message in the exception is clearer:
$ ./jdk-21-fix/jdk-21/bin/java ListFonts
Exception in thread "main" java.lang.RuntimeException: Fontconfig head is null, check your fonts or fonts configuration
at java.desktop/sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1262)
at java.desktop/sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:223)
...
As with the cases above, passing `fontconfig.properties` explicitly, resolves the problem, and the logical fonts get listed.
Obviously, I get another error if I try rendering the text:
Exception in thread "main" java.lang.Error: Probable fatal error: No physical fonts found.
at java.desktop/sun.font.SunFontManager.lambda$getDefaultPhysicalFont$0(SunFontManager.java:1034)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
...
A clearer error message was added by [JDK-8221741](https://bugs.openjdk.org/browse/JDK-8221741).
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13045#issuecomment-1507552539
More information about the client-libs-dev
mailing list