使用 Java2D 和 ServletOutputStream 不可预测?
我们有一些生产代码可以有效地执行此代码的操作:
这工作正常,但是我注意到一些有关的行为。
当请求 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 是什么。
有没有人遇到过这个问题,并且能够为其创建解决方法?
We have some code on production which is effectively doing what this code does:
This works fine, however I have noticed some concerning behaviour.
When a servlet is requested and some image data is returned to the browser via a ServletOutputStream, if another request is triggered before the image has finished painting itself on the screen, this will invariably crash the entire Jaguar server with the following trace:
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
I have found a couple of references online saying that what I am trying to do is unreliable, ie:
http://forums.sun.com/thread.jspa?trange=15&threadID=560000&forumID=20&tstart=0
However, to be honest, I am unclear as to what the EDT is.
Has anyone come across this issue, and been able to create a workaround for it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这听起来像是一些请求范围的变量被声明为 servlet 的实例变量。换句话说,代码不是线程安全的。在 Web 应用程序的生命周期中只有一个 servlet 实例。它在所有请求之间同时共享。每个请求都算作一个单独的线程。想象一下,您将变量 X(例如图像)声明为 servlet 的实例变量,并将其设置在线程 A(请求 A)中,然后在处理过程中线程 B 将使用相同的 servlet 并覆盖变量 X。这将在线程 A 中造成麻烦因为变量在处理到输出的过程中已被更改。
因此,您永远不应该将请求或会话范围的变量分配为 servlet 的实例变量:
而是这样
每个线程都有自己的变量。
也就是说,EDT 是“事件调度程序线程”。我不使用 Swing,所以我不能透露太多,但他试图告诉你应该保留所有变量 threadlocal (即在 servlet 的方法块中声明它们),这是有道理的)以避免它们在所有线程(请求)之间共享。
This sounds like that some request scoped variables are been declared as an instance variable of the servlet. In other words, the code is not threadsafe. There's only one instance of the servlet in webapplication's lifetime. It is shared concurrently between all requests. Each request counts as a separate thread. Imagine that you declare variable X (e.g. the image) as instance variable of the servlet and set it in thread A (request A) and then during processing thread B will use the same servlet and override variable X. This will cause trouble in thread A because the variable has been changed during processing it to the output.
Thus, you should never assign request or session scoped variables as instance variable of the servlet:
but rather so
this way each thread has its own variable.
That said, the EDT is the "Event Dispatcher Thread". I don't do Swing so I can't tell much about it, but it makes sense that he is trying to tell that you should keep all variables threadlocal (i.e. declare them all inside the servlet's method block) to avoid them being shared among all threads (requests).
我至少可以说出 EDT 的含义:那就是事件调度线程,所有 AWT 和 Swing 操作都在该线程中完成。
AFAIK,每个 JVM 只能有一个 EDT,因为这是在屏幕上输出图形的操作。我知道您的操作是无头的,但也许规则仍然适用。
我不确定正确的修复方法是什么。也许为每个请求线程生成一个 JVM?不知道是否实用...
I can at least say what the EDT it: that's the Event Dispatch Thread, the thread where all AWT and Swing operations are done.
AFAIK, there can be only one EDT per JVM, since that's the operations outputting graphics on screen. I understand your operation is headless, but perhaps the rule still applies.
I am unsure of what the correct fix could be. Perhaps spawning one JVM per request thread? Not sure if it is practical...
您的意思是同一个浏览器在检索和渲染上一页上的图像之前尝试导航到新的 URL?这可能会导致浏览器关闭用于检索图像的网络连接,这取决于 servlet 实现,可能会导致捕获并记录异常,尽管不存在真正的错误情况(浏览器只是在 servlet 之前断开了连接)已完成其工作)。
您在此处发布堆栈跟踪,但 JaguarConnection 类引发的实际异常是什么?
Do you mean that the same browser is trying to navigate to a new URL before the images on the previous page have been retrieved and rendered? This may cause the browser to close the network connections used to retrieve the images, which depending on the servlet implementation may cause an exception to be caught and logged, although no real error situation is present (the browser simply has dropped the connection before the servlet has finished its work).
You are posting a stack trace here, but what is the actual Exception, which is thrown by the JaguarConnection class?