`
gaozzsoft
  • 浏览: 424757 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Linux/Unix + RESIN/Tomcat 验证码无法显示的问题(ZT)

阅读更多

最近公司项目开发中遇到的一个问题,整理一下,和大家分享。

    验证码无法显示的问题,验证码的代码就是google上查找到的最常见的代码,服务器采用resin部署于linux或unix。不是常见的out.clear()问题,这次的问题发现在一个我压根就没有想到的地方,profile DISPLAY 环境变量。 

    1) 问题描述:
    登录页面等有验证玛显示的页面,通常可以正确显示验证码图片,但是在某些情况下发现验证码图片无法显示,并且目前只发生在linux/unix平台,windows下正常.而且和resin/jdk版本无关.

    bug的直接表现是表现为ie下是红叉,firefox下无实现.将验证码图片的地址在ie输入框中输入,则页面报错:

Java代码 复制代码 收藏代码
  1. 500 Servlet Exception   
  2. java.lang.NoClassDefFoundError   
  3.     at java.lang.Class.forName0(Native Method)   
  4.     at java.lang.Class.forName(Class.java:164)   
  5.     at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)   
  6.     at java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1141)   
  7.         at com.asiainfo.aimc.wmail.action.CreateImageServlet.doGet(CreateImageServlet.java:104)  
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) 测试代码分析

Java代码 复制代码 收藏代码
  1. public class Test {   
  2.     public static void main(String[] args) {   
  3.         String nm = (String) java.security.AccessController.doPrivileged   
  4.         (new sun.security.action.GetPropertyAction   
  5.          ("java.awt.graphicsenv"null));   
  6.            
  7.         System.out.println(nm);   
  8.            
  9.         try {   
  10.             Class.forName(nm).newInstance();   
  11.         } catch (Throwable e) {   
  12.             System.out.println("error=" + e.getClass().getName());   
  13.                
  14.             e.printStackTrace();   
  15.         }    
  16.     }   
  17. }  
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

    报错,打印为:

Java代码 复制代码 收藏代码
  1. sun.awt.X11GraphicsEnvironment   
  2. Throwable=java.lang.InternalError   
  3. java.lang.InternalError: Can't connect to X11 window server using '10.3.18.16' as the value of the DISPLAY variable.   
  4.         at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)   
  5.         at sun.awt.X11GraphicsEnvironment.access$000(X11GraphicsEnvironment.java:53)   
  6.         at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:142)   
  7.         at java.security.AccessController.doPrivileged(Native Method)   
  8.         at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:131)   
  9.         at java.lang.Class.forName0(Native Method)   
  10.         at java.lang.Class.forName(Class.java:164)   
  11.         at Test.main(Test.java:13)  
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的错误处理,不清楚这里的具体处理,不方便继续追查,作罢。

 

方案二:

Linux环境下对java图片类的支持不够,需要添加如下配置、方可加载图片环境:(或置于/etc下profile 配置文件中 /etc/profile文件)

tomcat下bin的启动文件,startup.sh中修改添加如下: export CATALINA_OPTS="-Djava.awt.headless=true"即可。

分享到:
评论

相关推荐

    Linux/UNIX系统编程手册源码

    1. **UNIX/Linux系统接口**:在UNIX和Linux系统中,程序员通常通过系统调用来与操作系统进行通信。这些调用包括打开、关闭文件,读写数据,创建和管理进程,以及处理网络通信等。例如,`open()`用于打开文件,`read...

    Linux/UNIX系统编程手册课后习题代码

    《Linux/UNIX系统编程手册》是一本经典的教材,它深入浅出地介绍了Linux和UNIX操作系统下的编程接口。这本书涵盖了各种核心API,包括文件操作、进程管理、网络通信、信号处理等,是学习系统级编程的重要参考资料。...

    《LINUX/UNIX系统编程手册》((德)Michael Kerrisk )随书代码完整版

    《LINUX/UNIX系统编程手册》((德)Michael Kerrisk ),上下册,经典的LINUX/UNIX下C语言编程教材,这是这本书所用到的所有代码,包涵所有头文件,亲测在LINUX下完美运行

    linux/unix网络编程-甘刚,,linux编程.ppt

    ,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt,linux编程.ppt

    用Linux/UNIX Shell编程语言设计系统监控程序.pdf

    在Linux/UNIX环境中,命令who可以显示当前系统中工作的用户与文件系统情况,但是为了将这些信息显示出来,需要使用过滤器awk提取行中信息。命令df可以检查文件系统的情况,显示设备名、文件系统类型、容量、已用容量...

    Linux/UNIX系统编程手册(源代码)

    《Linux/UNIX系统编程手册》是一本权威的指南,涵盖了操作系统接口、系统调用和C库函数等核心主题。这份源代码是该手册的实践部分,允许开发者在Linux环境中深入理解并实践书中所述的编程技术。以下是基于这些信息的...

    linux/unix系统编程手册(下)

    《Linux/Unix系统编程手册(下)》是深入理解Linux和Unix操作系统内核与系统编程不可或缺的参考书籍。这本书详细阐述了在这些操作系统环境下进行程序设计、系统调用、网络编程以及文件操作等方面的关键概念和技术。 ...

    Linux-UNIX系统编程手册.pdf

    Linux/UNIX系统编程是计算机科学领域中的一项核心技术,它主要涉及使用C语言对Linux或UNIX系统提供的底层接口进行操作。系统编程允许开发者执行诸如进程控制、文件操作、信号处理、进程间通信(IPC)以及网络编程等...

    asm.zip_Linux/Unix编程

    【标题】"asm.zip_Linux/Unix编程" 文件包涵盖了多个与Linux/Unix系统相关的编程主题,特别是关于URI(统一资源标识符)和UriBuilder类的使用。在Linux和Unix环境中,开发人员经常需要处理这些类来构建和操作URLs,...

    《LINUX/UNIX系统编程手册 上》.((德)Michael Kerrisk ).part2

    《LINUX/UNIX系统编程手册 上》.((德)Michael Kerrisk ),经典的linux/unix下c语言编程手册,分上下册,每册有150M,由于上传权限,是能把每册分割成3份上传

    linux/unix 系统编程手册

    《Linux/Unix 系统编程手册》是一本深入探讨Linux和Unix系统编程的权威著作,由德国专家Michael Kerrisk撰写,并由孙剑等翻译成中文,由人民邮电出版社出版。这本书涵盖了广泛的系统编程主题,旨在帮助开发者理解和...

    RSGLXT-master_Linux/Unix编程_

    《RSGLXT-master:Linux/Unix编程在人事管理系统中的应用》 RSGLXT-master 是一个专为人事管理设计的系统,充分利用了Linux/Unix平台的强大功能,为企业的员工信息管理提供了高效、稳定且灵活的解决方案。Linux/...

    LINUX.UNIX系统编程手册(下册)

    《linux/unix系统编程手册(上、下册)》是介绍linux与unix编程接口的权威著作。linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。...

    XMS.rar_Linux/Unix编程

    【标题】"XMS.rar_Linux/Unix编程" 涉及的是在Linux或Unix操作系统环境下进行程序开发的知识,特别是与Delphi相关的编程实践。在Linux/Unix系统中,编程通常涉及C语言或C++,但这个特定的案例中提到了“Hand C SMS ...

    Linux/UNIX系统编程手册.part2

    《Linux/UNIX系统编程手册(上、下册)》是介绍Linux与UNIX编程接口的权威著作。Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。...

    Linux/UNIX系统编程手册.part1

    《Linux/UNIX系统编程手册(上、下册)》是介绍Linux与UNIX编程接口的权威著作。Linux编程资深专家Michael Kerrisk在书中详细描述了Linux/UNIX系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。...

    Linux/UNIX系统编程手册 上册

    《linux/unix系统编程手册(上、下册)》是介绍linux与unix编程接口的权威著作。linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。...

    lrkx.rar_Linux/Unix编程

    开发者需要熟悉RTP协议,以及如何在Unix/Linux系统上实现它。 6. **用户界面(UI)**:描述中的“可视化”可能意味着资源包中包含了图形用户界面的代码。这可能涉及到Qt、GTK+或wxWidgets等跨平台库的使用,用于创建...

    exercise_one_due2v3_Linux/Unix编程_

    【描述】中的文字“很好周年活动赛纳好的那可视电话将上的还是那的呢”似乎是一段错误的或不相关的文本,可能是一个误解或者输入错误,因此无法从中提取与Linux/Unix编程相关的信息。 【标签】"due2v3 Linux/Unix...

    IQWG.zip_Linux/Unix编程

    【标题】"IQWG.zip_Linux/Unix编程"与描述中的"windows mobile 6 SDK 操作outlook通讯簿"看似不直接相关,但实际上,这可能是由于文件命名的误导。从标签"linux/unix编程"来看,我们可以推断出讨论的核心是关于在...

Global site tag (gtag.js) - Google Analytics