剖析在WAS 6.1.0.19上碰到/snoop时执行不完整而出现ClassFormatError

关键字: WAS Linux 6.1.0.19 snoop ClassFormatError

环境RedHat Linux + WAS 6.1.0.19
部署默认的应用程序 DefaultApplication.ear,访问 /snoop时,出现页面显示不完整,只显示 Servlet Name: 并到 Request Information: 这两项的内容,
然后在页面的源码最下面有一行,虽然源码在最后一行,但是显示却是显示在表格上方,即在 Request Information: 下面
Java代码 复制代码
  1. java.lang.ClassFormatError com/ibm/ws/webcontainer/srt/SRTServletRequest$2 unexpected EOF at offset=1240  
java.lang.ClassFormatError com/ibm/ws/webcontainer/srt/SRTServletRequest$2 unexpected EOF at offset=1240


于是只好看此君隐藏在哪个jar里了,通过 JarClassFind 发现在 AppServer/plugins/com.ibm.ws.webcontainer_2.0.0.jar 中。

于是只能通过测试此包是否真的有问题。拷贝一个到另一个目录下,然后执行
Java代码 复制代码
  1. jar xvf com.ibm.ws.webcontainer_2.0.0.jar  
jar xvf com.ibm.ws.webcontainer_2.0.0.jar

在执行解压的过程当中会出现如下错误:
Java代码 复制代码
  1. java.util.zip.ZipException: invalid entry size (expected 1240 but got 1242 bytes)   
  2.     at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java(Compiled Code))   
  3.     at java.util.zip.ZipInputStream.read(ZipInputStream.java(Compiled Code))   
  4.     at sun.tools.jar.Main.extractFile(Main.java(Compiled Code))   
  5.     at sun.tools.jar.Main.extract(Main.java:718)   
  6.     at sun.tools.jar.Main.run(Main.java:228)   
  7.     at sun.tools.jar.Main.main(Main.java:994)  
java.util.zip.ZipException: invalid entry size (expected 1240 but got 1242 bytes)
    at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java(Compiled Code))
    at java.util.zip.ZipInputStream.read(ZipInputStream.java(Compiled Code))
    at sun.tools.jar.Main.extractFile(Main.java(Compiled Code))
    at sun.tools.jar.Main.extract(Main.java:718)
    at sun.tools.jar.Main.run(Main.java:228)
    at sun.tools.jar.Main.main(Main.java:994)

只能说明是包坏了,从另一台机器上面执行同样的解压测试,OK,一切正常,那就下载一个过来,覆盖后重新启动之即可。

附Java Doc的解释为:
Java代码 复制代码
  1. public class ClassFormatError extends LinkageError  
public class ClassFormatError extends LinkageError

当 Java 虚拟机试图读取类文件并确定该文件存在格式错误或无法解释为类文件时,抛出该错误。

Java代码 复制代码
  1. unexpected EOF at offset=1240  
unexpected EOF at offset=1240
,应当在1240结束,但却没有。

Java代码 复制代码
  1. expected 1240 but got 1242 bytes  
expected 1240 but got 1242 bytes
,变多了2个字节,呵呵:)
由于在生产环境,坏的包无法拿出来,放上本机正常包的面目,如下图:



真是见怪不怪了。

正常情况下/snoop接下来应当是显示 Request headers: 相关的内容了。

剖析一下看。。。
Java代码 复制代码
  1. SnoopServlet.java   
  2.                 e = req.getParameterNames();   
  3.                 if ( e.hasMoreElements() )   
  4.                 {   
  5.                         out.println("<h2>Servlet parameters (Single Value style):</h2>");   
  6.                         out.println("<TABLE Border=/"2/" WIDTH=/"65%/" BGCOLOR=/"#DDDDFF/">");   
  7.                         while ( e.hasMoreElements() )   
  8.                         {   
  9.                                 String name = (String)e.nextElement();   
  10.                                 out.println("<tr><td>" + name + "</td><td>" + req.getParameter(name) + "</td></tr>");   
  11.                         }   
  12.                         out.println("</table><BR><BR>");   
  13.                 }  
SRTServletRequest.java
Java代码 复制代码
  1.             public Enumeration getAttributeNames()   
  2.             {   
  3. /* 225*/        if(TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())   
  4. /* 226*/            Tr.debug(tc, "getAttributeNames [" + this + "]");   
  5. /* 228*/        return new Enumeration() {   
  6.   
  7.                     public boolean hasMoreElements()   
  8.                     {   
  9. /* 231*/                return iter.hasNext();   
  10.                     }   
  11.   
  12.                     public Object nextElement()   
  13.                     {   
  14. /* 235*/                return iter.next();   
  15.                     }   
  16.   
  17.                     private Iterator iter;   
  18.   
  19.                        
  20.                     {   
  21. /* 229*/                iter = _srtRequestHelper._attributes.keySet().iterator();   
  22.                     }   
  23.         }  
说明了什么问题?匿名类也是仅在需要的时候才去Load,而不是跟主类一并全Load进去。于是 SnoopServlet可以执行一部分,而后面才出错。
Logo

更多推荐