浏览 6106 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-10-19
验证码无法显示的问题,验证码的代码就是google上查找到的最常见的代码,服务器采用resin部署于linux或unix。不是常见的out.clear()问题,这次的问题发现在一个我压根就没有想到的地方,profile DISPLAY 环境变量。 1) 问题描述: 登录页面等有验证玛显示的页面,通常可以正确显示验证码图片,但是在某些情况下发现验证码图片无法显示,并且目前只发生在linux/unix平台,windows下正常.而且和resin/jdk版本无关. bug的直接表现是表现为ie下是红叉,firefox下无实现.将验证码图片的地址在ie输入框中输入,则页面报错: 500 Servlet Exception java.lang.NoClassDefFoundError at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:164) at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68) at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1141) at com.asiainfo.aimc.wmail.action.CreateImageServlet.doGet(CreateImageServlet.java:104) 这里的java.lang.NoClassDefFoundError 极其误导人,一直以为是CLASSPATH或者jar包的问题,所以反复检查resin和jdk版本。 始终无法找到问题,只好尝试追查jdk源码,看到底发生了什么。 2) jdk源码追查 调用的servlet: BufferedImage bi = new BufferedImage(...) Graphics2D g = bi.createGraphics(); 查jdk: BufferedImage.createGraphics(): GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); 再查GraphicsEnvironment.getLocalGraphicsEnvironment: String nm = (String) java.security.AccessController.doPrivileged (new sun.security.action.GetPropertyAction ("java.awt.graphicsenv", null)); ...... localEnv = GraphicsEnvironment) Class.forName(nm).newInstance(); ...... 问题应该和nm有关,这里明显是一个类似工厂模式的设计,"java.awt.graphicsenv"到nm 然后Class.forName() 生成GraphicsEnvironment对象。 由于代码在jdk中,不方便修改,因此单独将这些代码提出来到简单的测试类 Test.java: 3) 测试代码分析 public class Test { public static void main(String[] args) { String nm = (String) java.security.AccessController.doPrivileged (new sun.security.action.GetPropertyAction ("java.awt.graphicsenv", null)); System.out.println(nm); try { Class.forName(nm).newInstance(); } catch (Throwable e) { System.out.println("error=" + e.getClass().getName()); e.printStackTrace(); } } } 在windows平台下运行,结果正常,打印: sun.awt.Win32GraphicsEnvironment 将代码放到出问题的resin安装所在的linux平台,手工编译运行: javac Test.java java -cp . Test 报错,打印为: sun.awt.X11GraphicsEnvironment Throwable=java.lang.InternalError java.lang.InternalError: Can't connect to X11 window server using '10.3.18.16' 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 Test.main(Test.java:13) 从错误信息" Can't connect to X11 window server using '10.3.18.16' as the value of the DISPLAY variable."来看,和DISPLAY环境变量有关 执行unset再运行可以发现问题消失: $> unset DISPLAY $> java -cp . Test sun.awt.X11GraphicsEnvironment $> 在此情况下(unset DISPLAY )下重新启动resin,发现验证码可以正常显示。 4) 解决的方法: 必须保证resin运行时DISPLAY 环境变量没有设置,如果resin运行的环境有其他要求必须使用DISPLAY,则可以在运行resin前使用unset清除. 建议的简单而有效的方法是直接修改resin/bin/httpd.sh文件,在第二行(具体行数无所谓,但必须在最后一行前)插入: #! /bin/sh unset DISPLAY #.... 5)疑惑 1. Can't connect to X11 window server using '10.3.18.16' as the value of the DISPLAY variable 为什么要去连X11 window server ?不懂 2. 从Test.java运行看抛出的是Error : java.lang.InternalError,但是页面上显示的是java.lang.NoClassDefFoundError,看了看源代码也没有发现先catch 后throws的错误处理,不清楚这里的具体处理,不方便继续追查,作罢。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-10-19
问题答案很容易在网上查到。类Unix系统里面如果主机上面没有带显示器的话,需要启动虚拟界面进程,此进程在系统安装时是可以选装的(openwin或X11)。
|
|
返回顶楼 | |
发表时间:2007-10-19
我google了一下"验证码 DISPLAY",没有发现相关的内容。
不过发现google的搜索引擎实在太强了,我刚发了这个帖子,才15分钟就在google上找到了我自己的帖子,简直快的有些变态了...... 顺便百度了一下,呵呵,没有找到。 |
|
返回顶楼 | |
发表时间:2007-10-19
google "unix BufferedImage.getGraphics"
|
|
返回顶楼 | |
发表时间:2007-10-22
搜索这个“Can't connect to X11 window server using ”你会找到需要的答案的。
|
|
返回顶楼 | |