解决Linux Ubuntu18下验证码报错问题

运行环境:

Ubuntu 18、jdk_1.8.2u231、jfinal-undertow 2.1、jfinal 4.9

本地环境没有问题,部署服务器报错。来官网找了下解决办法,发现有同样的问题,但未解决:

传送门:【jfinal自带的登录验证码问题 http://www.jfinal.com/feedback/5761

错误日志内容:

java.lang.RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class com.jfinal.captcha.CaptchaRender
	at com.jfinal.aop.Invocation.invoke(Invocation.java:107)
	at com.jfinal.core.ActionHandler.handle(ActionHandler.java:89)
	at com.jfinal.plugin.druid.DruidStatViewHandler.handle(DruidStatViewHandler.java:81)
	at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:90)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.jfinal.captcha.CaptchaRender
	at com.jfinal.render.RenderFactory.getCaptchaRender(RenderFactory.java:179)
	at com.jfinal.core.Controller.renderCaptcha(Controller.java:1292)
	at com.jmult._admin.login._LoginController.captcha(_LoginController.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.jfinal.aop.Invocation.invoke(Invocation.java:97)
	... 34 more


根据波总的回答找到了方向:

image.png

解决过程

1、安装相关字体

apt-get install ttf-dejavu

2、安装字体的依赖包

sudo apt-get install liberation-*
sudo apt-get install font-manager

以上操作完成后,不报错了,但还是不行,报以下错误:

java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:264)
	at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
	at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
	at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1181)
	at com.jfinal.captcha.CaptchaRender.drawGraphic(CaptchaRender.java:142)
	at com.jfinal.captcha.CaptchaRender.render(CaptchaRender.java:95)
	at com.jfinal.core.ActionHandler.handle(ActionHandler.java:114)
	at com.jfinal.plugin.druid.DruidStatViewHandler.handle(DruidStatViewHandler.java:81)
	at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:90)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

验证码采用awt图形处理并内存中生成,java程序会去寻找linux上的图形界面是否启动 ,如linux缺少组件则, 缺少了显示设备、键盘或鼠标会报这个错误。

所以需要开启无头模式, Headless模式是系统的一种配置模式 , 开始激活headless模式,告诉程序,现在你要工作在Headless mode下,就不要指望硬件帮忙了,你得自力更生,依靠系统的计算能力模拟出这些特性来继续。

网上基本上都是通过设置tomcat来解决:

在tomcat/bin/catalina.sh里加入 

JAVA_OPTS="$JAVA_OPTS -Djava.awt.headless=true

jfinal undertow项目解决办法,在配置文件中设置:

public void configConstant(Constants me) {
    System.setProperty("java.awt.headless","true");
}


完美解决:

image.png

评论区

JFinal

2020-08-26 22:55

这个办法极好,点赞 + 收藏

前不久 @eova 作者也提出过要添加这个支持,我正考虑要添加到 jfinal 新版本中去:
https://blog.csdn.net/wodeyuer125/article/details/50502914
原因是windows内核集成了gui,而linux上没有启动x server
解决办法:
1.启动x server
2.在java运行参数上加-Djava.awt.headless=true
用tomcat 和 Undertow 都可能遇到这个问题, 尤其是 Centos 7

就是不知道开启这个配置有没有啥副作用:
System.setProperty("java.awt.headless","true");

JFinal

2020-08-26 22:57

此外,你碰到的这个问题,不知道能不能同时解决下面这个验证码文字是乱码的问题:
https://jfinal.com/share/411

如果能同时解决就极好了

听风道长

2020-08-27 13:15

@JFinal 没试过中文,我试试看

JFinal

2020-10-02 16:36

@听风道长

由于某些 linux 发行版缺少缺少显示设备、键盘或鼠标,无法支持 Graphics、Font、Color、ImageIO、Print、Graphics2D 等类的使用

jfinal 4.9.02 新增一个配置来解决:
me.setToJavaAwtHeadless();

有了上面这个配置,不必再折腾 linux 操作系统

听风道长

2020-10-09 12:08

@JFinal 厉害了我的波大

东泠

2022-07-27 13:36

tomcat 8.5 加了之后为啥还报这个错