情境:
java web程序中,页面包含图形的展示,是使用jfreechart来开发的。war包部署在RHEL 5.5环境下的tomcat中。
1 在服务器(服务器默认启动为图形界面)本机上启动tomcat,在客户端浏览器上查看jfreechart图形正常;
2 远程通过ssh启动服务器上的tomcat,在客户端浏览器上查看jfreechart图形为小红叉;
先将异常部分贴出:
java.lang.InternalError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.access$000(X11GraphicsEnvironment.java:53)
at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:142)
at java.security.AccessController.doPrivileged(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:131)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
at sun.awt.X11.XToolkit.<clinit>(XToolkit.java:96)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at java.awt.Toolkit$2.run(Toolkit.java:821)
at java.security.AccessController.doPrivileged(Native Method)
at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:804)
at javax.swing.UIManager.initialize(UIManager.java:1236)
at javax.swing.UIManager.maybeInitialize(UIManager.java:1219)
at javax.swing.UIManager.getDefaults(UIManager.java:529)
at javax.swing.UIManager.getColor(UIManager.java:563)
at org.jfree.chart.JFreeChart.<clinit>(JFreeChart.java:261)
at org.jfree.chart.ChartFactory.createLineChart(ChartFactory.java:1242)
at cfca.xfraud.management.service.activity.ActivityStatisticsService.getEntityForm(ActivityStatisticsService.jav
a:325)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:592)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:
182)
…………分析以上异常已足够,剩下的异常栈信息忽略。
经过研究,发现该问题更深一步是这样:
1 如果以init 5的级别启动REHL 5.5系统,再启动tomcat,在客户端浏览器上查看jfreechart图形,图形显示正常;
2 如果以init 3的级别启动RHEL 5.5系统,再启动tomcat,在客户端浏览器上查看jfreechart图形,图形显示为小红叉;
这是很重要的结论,这个错误是因为图表程序是通过AWT实现的,AWT会调用操作系统本地窗口资源绘图,windows对此支持很好,
在linux下如果没有进到X window,AWT就不能绘图。
而且,通过查看异常的堆栈,发现at org.jfree.chart.JFreeChart.<clinit>(JFreeChart.java:261)这个异常,此时查找jfreechart官网的作者对该问题的解答:Web-Applications cannot have a Swing-GUI.也就是说,JFreechart采用AWT来绘图,如果没有图形界面,jfreechart里面所用到的
java.awt.Toolkit
java.awt.Color
java.awt.Rectangle
java.awt.Font
java.awt.FontMetrics
java.awt.image.ColorModel
等一系列包,均不能够使用。
使用了tomcat远程调试,将项目中所使用的jfreechart-1.0.13.jar源码下载,发现确实是跟踪到这行报错:
JFreeChart chart = ChartFactory.createLineChart("交易量统计图", "时间(" + units + ")" + time, "数量", dataset, PlotOrientation.VERTICAL, true, false, false);
createLineChart方法里面会调用的JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT,plot, legend);
而JFreeChart.DEFAULT_TITLE_FONT是public static final Font DEFAULT_TITLE_FONT = new Font("SansSerif", Font.BOLD, 18);
也就是说,用了awt的Font类。因为JFreeChart(String title, Font titleFont, Plot plot,boolean createLegend) 这个构造函数,本来就用的是Font,修改源码的方式可能会很麻烦,作罢。
问题应该已经研究的很清楚了。
(http://www.jfree.org/phpBB2/viewtopic.php?p=58565&sid=96ed91d7c0d71ba11e988201cbaafb47 jfreechart网站)
网上关于Can't connect to X11 window server的解决方案如下:
1 export DISPLAY=:0,然后重启服务器
已验证,无效。
2 在JVM中加入-Djava.awt.headless=true
对于tomcat ,可以修改catalina.sh,加入:CATALINA_OPTS="$CATALINA_OPTS -Djava.awt.headless=true"
已验证,无效
自己研究的解决方法:
3 调用ChartUtilities.writeChartAsPN
将每个chart存为图片到硬盘上,然后通过页面加载,这种方法,勉强解决该问题,但必须修改程序。
4 修改tomcat的startup.sh
加入export CATALINA_OPTS="-Djava.awt.headless=true",问题得到完美解决。
也就是说,init 3启动级别下,这种方式可以解决java awt的问题。