tomcat 中 java.awt.Rectangle 的 NoClassDefFoundError 8

NoClassDefFoundError for java.awt.Rectangle in tomcat 8

我正在将一个小型 Java servlet 部署到 tomcat 8。它绘制图像并将其保存到硬盘驱动器。它使用 java.awt.Rectangle、java.awt.Image 和 java.awt.Graphics2D classes。相关代码如下。

int WIDTH = 200;
int HEIGHT = 250;

Rectangle drawArea = new Rectangle(WIDTH, HEIGHT);

Image image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = (Graphics2D) image.getGraphics();

//...
//use the dimensions of the drawArea to draw something on the gw
//...

在Eclipse开发中完美运行。

但是,当我使用 maven 打包并将其部署到具有标准 tomcat 8 运行 作为服务的外部服务器时,它抱怨无法找到 java.awt.Rectangle class。

服务器运行 OpenJDK (1.7.0_71) 和 tomcat 8 (运行 -Djava.awt.headless=true)。列出tomcat进程(ps -fp)的结果如下:

jsvc.exec -Dcatalina.home=/usr/share/tomcat8 -Dcatalina.base=/usr/share/tomcat8 -Djava.io.tmpdir=/var/tmp/tomcat8/temp -Djava.awt.headless=true -cp /usr/share/java/commons-daemon.jar:/usr/share/java/eclipse-ecj.jar:/usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar -user tomcat8 -java-home /usr/lib/jvm/default-runtime -pidfile /var/run/tomcat8.pid -errfile SYSLOG -outfile SYSLOG org.apache.catalina.startup.Bootstrap

包含 java.awt.Rectangle 的 rt.jar 位于标准 OpenJDK lib 目录 (/usr/lib/jvm/default-runtime/lib/rt.jar) 下的文件系统中。 HI 在 tomcat 参数中未被 -cp 明确引用,恕我直言,它应该已经在 class 路径中。如果我明确地添加它,它不会改变任何东西:

jsvc.exec -Dcatalina.home=/usr/share/tomcat8 -Dcatalina.base=/usr/share/tomcat8 -Djava.io.tmpdir=/var/tmp/tomcat8/temp -Dderby.system.home=/var/lib/derby -Djava.awt.headless=true -cp /usr/share/java/commons-daemon.jar:/usr/share/java/eclipse-ecj.jar:/usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar:/usr/lib/jvm/default-runtime/lib/rt.jar -user tomcat8 -java-home /usr/lib/jvm/default-runtime -pidfile /var/run/tomcat8.pid -errfile SYSLOG -outfile SYSLOG org.apache.catalina.startup.Bootstrap

服务器是本地开发机器上的VM 运行最新的Arch linux 方便我测试servlet的部署。

所以问题是:我如何 获得 java.awt 在 tomcat 中生成图像的功能?

因为我在这上面花了好几个小时而且似乎没有进展,所以我决定把它从更有经验的人的头脑中反弹出来。非常感谢任何帮助。


编辑(2015.01.22,根据@Moonwalker的回答添加信息)

基本上,我所做的测试是,编辑 /etc/systemd/system/multi-user.target.wants/tomcat8.service 然后调用

systemctl daemon-reload
# and
systemctl restart tomcat8

我通过改变以下内容进行了 4 种编辑组合:

DISPLAY=localhost:0.0
or
DISPLAY=:0.0

-Djava.awt.headless=true
or
-Djava.awt.headless=false

所有组合结果:

threw an unexpected exception: java.lang.NoClassDefFoundError: Could not initialize class java.awt.Rectangle

rt.jar 确实有 java.awt.Rectangle class。


编辑(2015.01.23,按照@prunge 的建议添加了完整的堆栈跟踪)

Jan 22, 2015 9:49:07 AM org.apache.catalina.core.ApplicationContext log
                                                               SEVERE: Exception while dispatching incoming RPC call
                                                               com.google.gwt.user.server.rpc.UnexpectedException: Service method 'public abstract void com.mytest.imagegeom.GeometryService.doGeom(java.lang.String) throws java.lang.IllegalArgumentException' threw an unexpected exception: java.lang.NoClassDefFoundError: Could not initialize class java.awt.Rectangle
                                                                       at com.google.gwt.user.server.rpc.RPC.encodeResponseForFailure(RPC.java:415)
                                                                       at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:605)
                                                                       at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:333)
                                                                       at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:303)
                                                                       at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:373)
                                                                       at com.gooJan 22 09:49:07 test-host-deploygle.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(Abst
Jan 22 09:49:07 test-host-deploy jsvc.exec[8963]: ractRemoteServiceServlet.java:62)
                                                                       at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
                                                                       at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
                                                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
                                                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                                                       at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
                                                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
                                                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                                                       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
                                                                       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
                                                                       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
                                                                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
                                                                       at org.apache.catalina.valves.ErrorReportV
Jan 22 09:49:07 test-host-deploy jsvc.exec[8963]: alve.invoke(ErrorReportValve.java:79)
                                                                       at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
                                                                       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
                                                                       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
                                                                       at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
                                                                       at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
                                                                       at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
                                                                       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
                                                                       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
                                                                       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                                                       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
                                                                       at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.jav
Jan 22 09:49:07 test-host-deploy jsvc.exec[8963]: a:61)
                                                                       at java.lang.Thread.run(Thread.java:745)
                                                               Caused by: java.lang.NoClassDefFoundError: Could not initialize class java.awt.Rectangle
                                                                       at com.mytest.com.mytest.imagegeom.GeometryServiceImpl.createPNG(GeometryServiceImpl.java:488)
                                                                       at com.mytest.com.mytest.imagegeom.GeometryServiceImpl.convertStringToTree(GeometryServiceImpl.java:479)
                                                                       at com.mytest.com.mytest.imagegeom.GeometryServiceImpl.doGeom(GeometryServiceImpl.java:265)
                                                                       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                                                                       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
                                                                       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                                                                       at java.lang.reflect.Method.invoke(Method.java:606)
                                                                       at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:587)
                                                                       ... 28 more

我认为您应该尝试的第一件事是将 headless 选项设置为 false。

-Djava.awt.headless=false

您应该做的第二件事是将 DISPLAY 环境变量指向一个有效位置。没有它,awt 将无法工作,甚至无法生成背景图像。

DISPLAY=localhost:0.0 or DISPLAY=:0.0

您可能必须执行 xhost + 命令,但不一定。希望您的 Linux 安装已正确安装和配置虚拟显示器。

检查您使用的 JRE(以及 CLASSPATH)中是否包含 awt 类 的第三件事。

是的...应该没有必要将 JRE 系统 jar 文件显式添加到类路径中...默认情况下应该选择它们。但是您应该查看那些 jar 文件并验证是否包含 awt 包。

希望对您有所帮助。

有趣的是,在将 OpenJDK7 替换为 OpenJDK8 并删除 /etc/systemd/system/multi-user.target.wants/tomcat8.service 中的所有更改后,问题得到了解决。 tomcat 8 和 OpenJDK7 之间似乎存在某种不兼容性。异常现在神奇地消失了。我可以通过返回到 OpenJDK7 来重现它,但是我无法找出究竟是什么原因造成的。我将问题标记为已解决,但仍然欢迎您就此特殊行为提出任何意见。

亲切的问候。