使用Java2D和ServletOutputStream是不可预测的?

时间:2010-02-25 21:49:37

标签: java servlets java-2d

我们有一些生产代码可以有效地执行此代码的操作:

http://java.sun.com/products/java-media/2D/reference/faqs/index.html#Q_Can_I_use_Java2D_to_generate_d

这很好,但是我注意到了一些有关行为。

当请求servlet并且某些图像数据通过ServletOutputStream返回到浏览器时,如果在图像完成在屏幕上绘制之前触发了另一个请求,则这将使整个Jaguar服务器崩溃,并带有以下跟踪:

j  com.sybase.jaguar.servlet.JaguarConnection.writeClient([BII)V+0
j  com.sybase.jaguar.servlet.JagHttp11OutputStream.writeChunk()V+92
j  com.sybase.jaguar.servlet.JagHttp11OutputStream.writeOut()V+57
j  com.sybase.jaguar.servlet.ResponseImpl.flushBuffer(Z)V+93
j  com.sybase.jaguar.servlet.ResponseImpl.flushBuffer()V+17
j  com.sybase.jaguar.servlet.JaguarOutputStream.flush()V+19
j  javax.imageio.stream.FileCacheImageOutputStream.close()V+50
j  javax.imageio.stream.ImageInputStreamImpl.finalize()V+8

我在网上发现了一些参考资料,说我想做的事情是不可靠的,即:

http://forums.sun.com/thread.jspa?trange=15&threadID=560000&forumID=20&tstart=0

然而,说实话,我不清楚EDT是什么。

是否有人遇到此问题,并且能够为其创建解决方法?

3 个答案:

答案 0 :(得分:1)

我至少可以说它是什么EDT:那是事件调度线程,即完成所有AWT和Swing操作的线程。
AFAIK,每个JVM只能有一个EDT,因为这是在屏幕上输出图形的操作。我知道你的行动是无头的,但也许规则仍然适用 我不确定正确的解决办法是什么。也许每个请求线程产生一个JVM?不确定它是否实用......

答案 1 :(得分:1)

这听起来有些请求作用域变量已被声明为servlet的实例变量。换句话说,代码不是线程安全的。在webapplication的生命周期中,只有一个servlet实例。它在所有请求之间同时共享。每个请求都算作一个单独的线程。想象一下,您将变量X(例如图像)声明为servlet的实例变量并将其设置在线程A(请求A)中,然后在处理过程中,线程B将使用相同的servlet并覆盖变量X.这将导致线程A出现问题因为在处理变量到输出期间变量已被更改。

因此,您永远不应将请求或会话范围变量分配为servlet的实例变量:

public class ImageServlet extends HttpServlet {

    private Image image;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        this.image = imageDAO.find(request.getPathInfo()); // Not threadsafe!! image is been shared among all requests.
        // ...
    }
}

但更确切地说

public class ImageServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        Image image = imageDAO.find(request.getPathInfo()); // Threadsafe.
        // ...
    }
}

这样每个线程都有自己的变量。

那就是说,EDT是“Event Dispatcher Thread”。我不做Swing,所以我不能说太多,但是有意义的是他试图告诉你应该保留所有变量 threadlocal (即在servlet的方法块中声明它们全部)避免它们在所有线程(请求)之间共享。

答案 2 :(得分:0)

您是说在检索并呈现上一页上的图像之前,同一浏览器是否尝试导航到新的URL?这可能会导致浏览器关闭用于检索映像的网络连接,这取决于servlet实现可能会导致异常被捕获并记录,尽管不存在真正的错误情况(浏览器只是在servlet之前删除了连接)已经完成了工作。)

您在此处发布堆栈跟踪,但JaguarConnection类抛出的实际异常是什么?