Cfimage suddenly causes "Could not initialize class java.awt.GraphicsEnvironment" after updating Ubuntu 20.04 LTS

Hi to all,

This is only a post for documentation because I’ve resolved it myself with the help of another post with a solution from @sbleon. Just posting it here for posterity because the exception is different. This issue suddenly came out of nowhere, happened after updating the OS with regular security patches.

The environment:
Lucee 5.3.8.139-RC (Default Lucee Linux Installer with manual upgrade to 5.3.8.139-RC Lucee.jar)
OS: Ubuntu 20.04 LTS (Linux (5.4.0-65-generic) 64bit
Servlet Container: Apache Tomcat/9.0.40
Java: 11.0.4 (AdoptOpenJDK) 64bit

The following code to create captcha images:

<cfimage base64="yes" action="captcha" text="Captcha!" difficulty="medium" height="50" width="200" fontSize="18" fonts="Comic Sans MS,Times New Roman">

Was causing the following exception:

Message
string Could not initialize class java.awt.GraphicsEnvironment$LocalGE
StackTrace
string lucee.runtime.exp.NativeException: Could not initialize class java.awt.GraphicsEnvironment$LocalGE at java.desktop/java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(Unknown Source) at java.desktop/java.awt.image.BufferedImage.createGraphics(Unknown Source) at org.lucee.extension.image.captcha.AbstractCaptcha.generate(AbstractCaptcha.java:80) at org.lucee.extension.image.captcha.AbstractCaptcha.generate(AbstractCaptcha.java:62) at org.lucee.extension.image.MarpleCaptcha.generate(MarpleCaptcha.java:45) at org.lucee.extension.image.tag.Image.doActionCaptcha(Image.java:324) at org.lucee.extension.image.tag.Image.doStartTag(Image.java:285) at home_cfm$cf.call(/home.cfm:140) at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:988) at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:911) at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:892) at application_cfc$cf.udfCall(/Application.cfc:331) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:106) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:344) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:217) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:648) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:570) at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1900) at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:436) at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:215) at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:42) at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2442) at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2432) at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2403) at lucee.runtime.engine.Request.exe(Request.java:44) at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1174) at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1120) at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97) at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51) at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:747) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:880) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1601) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Unknown Source) Caused by: java.lang.NoClassDefFoundError: Could not initialize class java.awt.GraphicsEnvironment$LocalGE … 53 more

Solution:

As suggested by @sbleon I’ve created/edited the file /opt/lucee/tomcat/bin/setenv.sh and added the following JVM system property to run Javas AWT in headless mode:

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

Restarted Lucee and the issue went away.

i think you need truetypefonts package get some X libs. Might be another package needed also.

1 Like

here’s the task about making this error less cryptic

https://luceeserver.atlassian.net/browse/LDEV-2619

I’m curious if this works?

System.setProperty("java.awt.headless", "true"); 

My configuration worked for almost a year. That libs/fonts were already working. It was just that jwt wasn’t in headless mode.

I thought it wouldn’t work by simply setting the variable like so, but the idea deserved a try. Result: Seems that the java.awt.headless system.property needs to be passed to the servlet engine on startup. As soon as the server starts, you can change the property programatically and it will populate the server.system.properties struct correctly but it won’t have any effect to java.awt.

However, tried it with Server.cfc startup listener (see here) because after seeing one of Michas videos a while ago I wanted to try that functionallity. That seems to work fine. But instead of using Server.cfc listener I’d prefere using Tomcats setenv.sh because sometimes I just want to delete server-context after upgrade/downgrade for a clean redeployment.