apline-tomcat镜像 "sun.awt.FontConfiguration.getVersion NullPointerException"问题解决
问题:
在使用apline/tomcat镜像的过程中,发现对于涉及图形类的应用报错:
java.lang.ExceptionInInitializerError: null
at org.apache.batik.bridge.SVGTextElementBridge.getFontList(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.SVGTextElementBridge.getAttributeMap(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.SVGTextElementBridge.fillAttributedStringBuffer(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.SVGTextElementBridge.buildAttributedString(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.SVGTextElementBridge.computeLaidoutText(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.SVGTextElementBridge.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.bridge.GVTBuilder.build(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.transcoder.image.ImageTranscoder.transcode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.transcoder.XMLAbstractTranscoder.transcode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
//中间省略部分日志
Caused by: java.lang.NullPointerException: null
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[na:1.8.0_151]
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) ~[na:1.8.0_151]
at sun.awt.FontConfiguration.init(FontConfiguration.java:107) ~[na:1.8.0_151]
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) ~[na:1.8.0_151]
at sun.font.SunFontManager$2.run(SunFontManager.java:431) ~[na:1.8.0_151]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_151]
at sun.font.SunFontManager.<init>(SunFontManager.java:376) ~[na:1.8.0_151]
at sun.awt.FcFontManager.<init>(FcFontManager.java:35) ~[na:1.8.0_151]
at sun.awt.X11FontManager.<init>(X11FontManager.java:57) ~[na:1.8.0_151]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_151]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_151]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_151]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_151]
at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_151]
at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) ~[na:1.8.0_151]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_151]
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:1.8.0_151]
at sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:201) ~[na:1.8.0_151]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:235) ~[na:1.8.0_151]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:263) ~[na:1.8.0_151]
at sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:94) ~[na:1.8.0_151]
at org.apache.batik.gvt.font.FontFamilyResolver.<clinit>(Unknown Source) ~[batik-all-1.7.jar:1.7+r608262]
... 114 common frames omitted
网上搜索了一下,比较有效的解决办法是装ttf-dejavu【参考1】,但好像是针对Debian系统的。
通过比较分析发现,出现该问题的时使用的是OpenJDK 1.8, 而使用Sun JDK 1.8则没有问题,因此,可以断定问题出在JDK环境上,而非alpine环境。
若要解决这个问题,1、是将OpenJDK换为Sun JDK; 2、是在Open JDK基础上讲所需的字体配置文件补全。
从时间经济上考虑,基于alpine的tomcat有使用Sun JDK镜像的,可以直接拿来使用,如果去研究完善Opend JDK,固然可以解决问题,但要花较多的时间,而且,alpine-tomcat极有可能会在不远的将来修复该缺陷。
所以最终决定找使用Sun JDK的apline-tomcat, 结果找到了docker.io/davidcaste/alpine-tomcat。
注意:
1、docker.io/davidcaste/alpine-tomcat tomcat目录放置位置与alpine/tomcat不同,docker.io/davidcaste/alpine-tomcat 镜像中,tomcat放置在/opt目录下;而alpin/tomcat镜像中,则放置在/usr/local目录下,在更好镜像后需要对相关的kubernetes deployment文件进行调整。
2、docker.io/davidcaste/alpine-tomcat 镜像的工作目录(WORKDIR)不是tomcat;
解决:在Dockerfile中,添加WORKDIR命令:WORKDIR /opt/tomcat
3、docker.io/davidcaste/alpine-tomcat没有设置缺省的运行命令,运行镜像时需要添加/opt/tomcat/bin/catalina.sh run, 显然没有alpine-tomcat方便
解决: 在Dockerfile中,添加RUN命令:ENV PATH=/opt/tomcat/bin:$PATH
CMD ["catalina.sh", "run"]
参考:
1、NullPointerException in Alpine JRE 8 Font #73. https://github.com/docker-library/openjdk/issues/73