星期二, 十一月 25, 2008

居然会遇到java的bug

在程序里用到了com.oreilly.servlet.multipart.BufferedServletInputStream的一段源码,居然会在运行的时候偶尔出现exeception,很是奇怪,跟踪了几次都无法找到原因,在google的时候,发现已经有人遇到此问题了,好像是jre或者application server的问题。不管是哪个层面的问题,反正已经超出我们能够理解的范畴了,记录一下。

根据http://www.servlets.com/soapbox/bugs.html网站的描述,已经确认是servlet的bug了。
Bug: File upload does not work with Apache JServ when uploading large binary files
Symptoms: When handling a file upload the com.oreilly.servlet.MultipartRequest class throws an ArrayIndexOutOfBoundsException.
Reason: JServ supports the older Servlet API 2.0 and in the API 2.0 source code for javax.servlet.ServletInputStream there's a bug in the readLine(byte[] buf, int off, int len) method where the len parameter is ignored, and as a result reading input lines that exceed the buf length will throw an ArrayIndexOutOfBoundsException.
Workaround: The com.oreilly.servlet library has implemented its own buffering to work around this issue. If you're using another library, upgrade to a server that supports Servlet API 2.1 or later.

http://www.javafaq.nu/java-example-code-1017.html
/**
* A BufferedServletInputStream wraps a
* ServletInputStream in order to provide input buffering and to
* avoid calling the the readLine method of the wrapped
* ServletInputStream.
*


* This is necessary because some servlet containers rely on the default
* implementation of the readLine method provided by the Servlet
* API classes, which is very slow. Tomcat 3.2, Tomcat 3.1, the JSWDK 1.0 web
* server and the JSDK2.1 web server are all known to need this class for
* performance reasons.
*


* Also, it may be used to work around a bug in the Servlet API 2.0
* implementation of readLine which contains a bug that causes
* ArrayIndexOutOfBoundsExceptions under certain conditions.
* Apache JServ is known to suffer from this bug.
*
* @author Geoff Soutter
* @version 1.1, 2001/05/21, removed block of commented out code
* @version 1.0, 2000/10/27, initial revision
*/


http://www.cs.unc.edu/Courses/jbs/documentation/oreilly/multipartparser/doc/com.oreilly.servlet.multipart.BufferedServletInputStream.html
java.lang.Object

+----java.io.InputStream

+----javax.servlet.ServletInputStream

+----com.oreilly.servlet.multipart.BufferedServletInputStream
public class BufferedServletInputStream
extends ServletInputStream A BufferedServletInputStream wraps a ServletInputStream in order to provide input buffering and to avoid calling the the readLine method of the wrapped ServletInputStream.
This is necessary because some servlet containers rely on the default implementation of the readLine method provided by the Servlet API classes, which is very slow. Tomcat 3.2, Tomcat 3.1, the JSWDK 1.0 web server and the JSDK2.1 web server are all known to need this class for performance reasons.
Also, it may be used to work around a bug in the Servlet API 2.0 implementation of readLine which contains a bug that causes ArrayIndexOutOfBoundsExceptions under certain conditions. Apache JServ is known to suffer from this bug.
Version:
1.1, 2001/05/21, removed block of commented out code
Author:
Geoff Soutter