目录

问题现象

问题原因:

问题解决:

容器环境下

非容器环境下


 

问题现象

Dockerfile基础镜像从 java:8

更换为 adoptopenjdk/openjdk8-openj9:alpine-slim 后

登录页面的验证码无法加载,并报错

2021-08-24 01:30:25.763 ERROR 1 --- [or-http-epoll-4] reactor.netty.http.server.HttpServer     : [id: 0xf73ab911, L:/172.23.0.4:8081 - R:/10.0.159.222:52873] 


java.lang.NoClassDefFoundError: sun.awt.X11FontManager (initialization failure)

	at java.lang.J9VMInternals.initializationAlreadyFailed(Unknown Source) ~[na:1.8.0_302]

	at java.lang.Class.forNameImpl(Native Method) ~[na:1.8.0_302]

	at java.lang.Class.forName(Unknown Source) ~[na:1.8.0_302]

	at sun.font.FontManagerFactory$1.run(Unknown Source) ~[na:1.8.0_302]

	at java.security.AccessController.doPrivileged(Unknown Source) ~[na:1.8.0_302]

	at sun.font.FontManagerFactory.getInstance(Unknown Source) ~[na:1.8.0_302]

	at java.awt.Font.getFont2D(Unknown Source) ~[na:1.8.0_302]

	at java.awt.Font.access$000(Unknown Source) ~[na:1.8.0_302]

	at java.awt.Font$FontAccessImpl.getFont2D(Unknown Source) ~[na:1.8.0_302]

	at sun.font.FontUtilities.getFont2D(Unknown Source) ~[na:1.8.0_302]


	at com.google.code.kaptcha.text.impl.DefaultWordRenderer.renderWord(DefaultWordRenderer.java:66) ~[kaptcha-2.3.2.jar!/:2.3.2]

	at com.google.code.kaptcha.impl.DefaultKaptcha.createImage(DefaultKaptcha.java:43) ~[kaptcha-2.3.2.jar!/:2.3.2]

	at com.jiean.gateway.service.impl.ValidateCodeServiceImpl.createCapcha(ValidateCodeServiceImpl.java:61) ~[classes!/:na]

	at com.jiean.gateway.handler.ValidateCodeHandler.handle(ValidateCodeHandler.java:33) ~[classes!/:na]

	at 
	at java.lang.Thread.run(Unknown Source) [na:1.8.0_302]

Caused by: java.lang.UnsatisfiedLinkError: fontmanager (libfreetype.so.6: cannot open shared object file: No such file or directory)

问题原因:

这种一般是出现在 docker部署,且使用了精简版的基础镜像,有多精简呢?精简到把字体都阉割掉了,好狠…
如果你的项目有字体相关操作,比如导出 excel,验证码,就会报上述异常。

对于一个Java服务器来说经常要处理一些图形元素,例如地图的创建或者图形和图表等。这些API基本上总是需要运行一个X-server以便能使用AWT(Abstract Window Toolkit,抽象窗口工具集)。

问题解决:

容器环境下

换个东西全一点的镜像;

FROM java:8

在构建镜像时安装字体,dockerfile增加命令:

RUN yum install dejavu-sans-fonts fontconfig -y

如果 container已经启动,又不想换,那就直接进到 container,安装字体:

yum install dejavu-sans-fonts fontconfig -y

非容器环境下

从代码层面手工设置了 System.setProperty("java.awt.headless","true"); 解决问题。

@SpringBootApplication
public class EbootApplication {
   public static void main(String[] args) {
      System.setProperty("java.awt.headless", "true");
      SpringApplication.run(EbootApplication.class, args);
   }
}

什么是Headless mode?Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。

一般是在程序开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,自力更生并依靠系统的计算能力模拟出这些特性来。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐