Could not initialize class sun.awt.X11GraphicsEnvironment,java.awt.HeadlessException解决办法

当遇到'Could not initialize class sun.awt.X11GraphicsEnvironment'异常时,可通过开启headless模式解决。在Linux上部署Java应用时,遇到验证码显示问题,尝试开启headless模式后,发现接口返回无图片并报错。最终解决方案是避免使用JFrame,改用FilteredImageSource和CropImageFilter来实现验证码生成,避免依赖图形环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结

出现Could not initialize class sun.awt.X11GraphicsEnvironment异常的话,开启headless就好了,开启的方法有好多,我这里总结一下:
可以在catalina.sh脚本中
1.加入CATALINA_OPTS=-Djava.awt.headless=true

2.或者在每处类似:

exec "\$_RUNJDB" "\$LOGGING_CONFIG" \$LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
        -Djava.endorsed.dirs="\$JAVA_ENDORSED_DIRS" -classpath "\$CLASSPATH" \
        -sourcepath "\$CATALINA_HOME"/../../java \
        -Djava.security.manager \
        -Djava.security.policy=="\$CATALINA_BASE"/conf/catalina.policy \
        -Dcatalina.base="\$CATALINA_BASE" \
        -Dcatalina.home="\$CATALINA_HOME" \
        -Djava.io.tmpdir="\$CATALINA_TMPDIR" \

的后边加入-Djava.awt.headless=true \(我的tomcat7上共有8处)

3.或者在JAVA_OPTS后边加入-Djava.awt.headless=true,我的脚本加入后为:
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS -Djava.awt.headless=true"

4.或者直接在当前用户的.bash_profile 文件后边加上export JAVA_OPTS=-Djava.awt.headless=true,然后source .bash_profile使配置生效。

上述方法都是等价的,如果加入后出现异常:

 ERROR advice.ControllerAdvice:44 - java.lang.IllegalStateException: Cannot create a session after the response has been committed java.lang.IllegalStateException: Cannot create a session after the response has been committed
        at org.apache.catalina.connector.Request.doGetSession(Request.java:3069)
        at org.apache.catalina.connector.Request.getSession(Request.java:2441)
        at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:897)
        at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:909)
        at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:238)
        at cn.edu.hdu.config.DrawCaptcha.getCode(DrawCaptcha.java:73)
        at cn.edu.hdu.controller.PublicController.getCaptcha(PublicController.java:127)

则可以试试在你的代码中 不要使用JFrame

踩坑记录

最近甲方突然提出了一个新需求,web端登录的时候,在用户输入密码错误过多的情况下,需要显示验证码,并输入验证码进行登录,感觉不是很难,从网上随便找了个Java生成验证码的类,并自己加了一些显示和隐藏的逻辑后,功能完成了,在Windows上也使用正常,但是部署到Linux上的时候出现了问题

问题

一开始部署到Linux服务器上之后,验证码显示不出来,于是测试了一下生成验证码的接口,果然报错了:
在这里插入图片描述
报错信息如下:

HTTP Status 500 - Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.
type Exception report

message Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.
	org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1260)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:206)
	net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:179)
	org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
	org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:232)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
	net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)

网上搜了一下,大部分都是说让开启headless模式,于是按照网上的说法,加上了-Djava.awt.headless=true

这里有的说让在CATALINA_OPTS后边加-Djava.awt.headless=true,有的让在多处-java.io.tmpdir="$CATALINA_TMPDIR" \后边加(大概有7 8处),有的让在JAVA_OPTS后边加,这里我试了一下,结果是一样的,都是不行。

我开启了headless模式后,请求验证码的接口确实是返回200正常了,但是接口的图片没有返回,并且没有任何返回值,查看tomcat日志后,发现报错:

java.awt.HeadlessException at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)

于是继续网上搜解决方案,发现网上针对这个错误的大部分解决方案都是关闭headless模式,也就是设置-Djava.awt.headless=false,芭比Q了,死锁了。

解决

在一个外国博主那里找到了答案,他的回答是:

I have resolved this problem by not using JFrame. Instead of JFrame I have used the following: FilteredImageSource myFilteredImageSource = new FilteredImageSource(image.getSource(), new CropImageFilter(x, y, crpHeight, crpWidth));

仔细查看我从网上找到的生成验证码的类,还真是继承了JFrame,于是我把继承JFrame的这部分去掉,发现他生成验证码的代码也没有报错,本地调试了一下发现没有问题,就部署到服务器上去了,本来都已经绝望了,没想到居然成功了,看来以后代码不能乱抄啊!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值