openjdk: NullPointerException in Alpine JRE 8 Font

JVM Version: 1.8.0_77-internal-alpine-r0-b03

INFO [CaptchaImpl] Initializing com.liferay.portal.captcha.simplecaptcha.SimpleCaptchaImpl
Fontconfig warning: ignoring C.UTF-8: not a valid language tag
ERROR [CaptchaPortletAction] null
java.lang.NullPointerException
    at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
    at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
    at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
    at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
    at sun.font.SunFontManager$2.run(SunFontManager.java:431)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.font.SunFontManager.<init>(SunFontManager.java:376)
    at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
    at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
    at java.awt.Font.getFont2D(Font.java:491)
    at java.awt.Font.access$000(Font.java:224)
    at java.awt.Font$FontAccessImpl.getFont2D(Font.java:228)
    at sun.font.FontUtilities.getFont2D(FontUtilities.java:180)
    at sun.font.StandardGlyphVector.initFontData(StandardGlyphVector.java:1126)
    at sun.font.StandardGlyphVector.init(StandardGlyphVector.java:1115)
    at sun.font.StandardGlyphVector.<init>(StandardGlyphVector.java:167)
    at java.awt.Font.createGlyphVector(Font.java:2545)
    at nl.captcha.text.renderer.DefaultWordRenderer.render(Unknown Source)
    at nl.captcha.Captcha$Builder.addText(Unknown Source)
    at com.liferay.portal.captcha.simplecaptcha.SimpleCaptchaImpl.getSimpleCaptcha(SimpleCaptchaImpl.java:243)
    at com.liferay.portal.captcha.simplecaptcha.SimpleCaptchaImpl.serveImage(SimpleCaptchaImpl.java:159)
    at com.liferay.portal.captcha.CaptchaImpl.serveImage(CaptchaImpl.java:100)
    at com.liferay.portal.kernel.captcha.CaptchaUtil.serveImage(CaptchaUtil.java:78)
    at com.liferay.portal.captcha.CaptchaPortletAction.serveResource(CaptchaPortletAction.java:42)

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 11
  • Comments: 31 (13 by maintainers)

Commits related to this issue

Most upvoted comments

@jasonmader Try installing the ttf-dejavu package and see what happens. It seems to fix things for me. although it does add 124 MiB of packages to the image

Update: There are 124 MiB of packages in the image total after adding ttf-dejavu. Looks like it actually adds about 20 MiB to the image:

$ docker images | grep jre-alpine
java                      8-jre-alpine-with-fonts   82a7a914a102        4 seconds ago       127.7 MB
java                      8-jre-alpine              fa6dc16ed7ae        4 days ago          108.3 MB

It seems like the underlying issue is that fontconfig can’t find any fonts in the java:8-jre-alpine image because there are no fonts:

$ docker run --rm java:8-jre-alpine find / -name '*.ttf'

The Debian-based image has just enough fonts to support the default JDK fonts, it seems:

$ docker run --rm java:8-jre find / -name '*.ttf'
/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf
/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf
/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf
/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf

These fonts come from the fonts-dejavu-core package, which is a transitive dependency of libfontconfig1 on Debian.

Same issue in jre-10 while generating excel reports, ubuntu 16.04 installing fontconfig ttf-dejavu solved this issues

full ack @jnunderwood Another idea might therefore be to add some “notable problems” in the docker hub description at https://hub.docker.com/_/openjdk/ which points out, that the alpine image is missing fonts, which might break the functionality of OpenJDK (may be there are some other issues which should be described).

installing ttf-dejavu packge fixed it.

FYI: Same problem seems to afflict openjdk:9-jdk (9-b158)

workaround as noted in #48

apt-get -y --no-install-recommends install libfontconfig1

Right. Sorry I missed that part in your original message.

The weird thing is that that error message comes from fontconfig, but it seems that java:alpine doesn’t have fontconfig installed. Perhaps fontconfig is statically linked into the JRE on Alpine?

I took a look at the source code for OpenJDK 8 and traced back that NPE (the starting point is here). It looks like the proximate issue is that there is no fontconfig.properties or fontconfig.bcf file (or any OS name-qualified variant), so readFontConfigFile(File) never calls loadProperties(InputStream) or loadBinary(InputStream) and the head variable is never initialized, resulting in a NullPointerException.

I’m not sure the apparent warning from fontconfig matters all that much, but that happens here. I’m not well-versed in C code, so that string parsing code makes my eyes glaze over and I’m not sure why it doesn’t like C.UTF-8, but it seems like the “-” in “UTF-8” may be throwing it off.

As an additional data point, when I call Charset.defaultCharset().name() in a java:alpine container, which is what FontConfiguration uses to determine the current encoding, it returns "UTF-8". It returns the same value when running under LANG=C.UTF8 or LANG=C.utf8.

I didn’t dig into Debian’s packaging of libfontconfig1 to see if they’re patching that part of fontconfig to avoid the warning.

I don’t think a _with_fonts image would improve much, as you still don’t know that you need this image (as there is no meaningful exception thrown). And if you actually know that you need this image, you can apply the appropriate RUN command in your Dockerfile.

AFAICT 8-jre-alpine still has that issue. 8-jre-slim works as expected. Can this only be fixed by installing a new package in the container?

Quite hard to debug and find the source of this error. For me it even crashed with diverse errors (which I paste, so somebody might find it on Google):

java.lang.NoClassDefFoundError: Could not initialize class org.apache.batik.bridge.DefaultFontFamilyResolver
	at org.apache.batik.bridge.UserAgentAdapter.getFontFamilyResolver(UserAgentAdapter.java:465)
	at org.apache.batik.bridge.BridgeContext.getFontFamilyResolver(BridgeContext.java:284)
	at org.apache.batik.bridge.SVGTextElementBridge.getFontList(SVGTextElementBridge.java:1518)
	at org.apache.batik.bridge.SVGTextElementBridge.getAttributeMap(SVGTextElementBridge.java:1597)

or

java.lang.ExceptionInInitializerError
	at org.apache.batik.bridge.UserAgentAdapter.getFontFamilyResolver(UserAgentAdapter.java:465)
	at org.apache.batik.bridge.BridgeContext.getFontFamilyResolver(BridgeContext.java:284)
	at org.apache.batik.bridge.SVGTextElementBridge.getFontList(SVGTextElementBridge.java:1518)

(I think there had also been a NullPointerException, but I could not find it anymore.)

Adding RUN apk add --no-cache ttf-dejavu to the Dockerfile fixes the issue.

I wonder if this could also be an upstream issue for the OpenJDK developers, as throwing those Exceptions is really not helpful to point out that there are fonts missing.

Also, I added ENV LC_CTYPE en_US.UTF-8 to avoid the Fontconfig warning in the log.