tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier>
Subject Re: AJP-APR failures on Tomcat 7.0.16 with ISAPI Redirector 1.2.32
Date Thu, 14 Jul 2011 10:59:48 GMT
eurotrans-Verlag wrote:
> Hi Rainer,
>> -----Original Message-----
>> From: Rainer Jung []
>> Sent: Thursday, July 14, 2011 12:17 AM
>> At least there was trouble about Java2D for several users in the past.
>> One such issue:
>> but you might find more.
>> Regards,
>> Rainer
> Thanks. In the meantime, I also came to that conclusion and replaced all
> instances of
> ImageIO.write(img, "PNG", response.getOutputStream())
> in my servlets/webapps with something like
> ByteArrayOutputStream bout = new ByteArrayOutputStream();
> ImageIO.write(img, "PNG", bout);
> bout.writeTo(response.getOutputStream());
> so that the ImageIO never sees the real OutputStream, and it seems to work
> fine (no more IllegalStateExceptions or "wrong message format" errors in the
> isapi log when using AJP-APR).
> Is that a good practice (using ByteArrayOutputStream, then copy it to the
> response) to dynamically generate Images and serve them to the clients?
> Also, is there any hint to this on the Tomcat documentation/wiki? Because I
> don't think it would be unusual to dynamically generate images and serve
> them to clients using the ImageIO, and I think it could be a bit frustrating
> to find the actual problem if one doesn't know this.

As a comment purely from a general programming point of view, not a Java/Tomcat 
programming point of view :

I am not familiar with the ByteArrayOutputStream, but from your usage of it above it seems

to be a buffer in memory to which one can write, and with a special "writeTo" method which

must be an efficient way to copy its contents to another stream.

If so, whether it is good practice or not would depend entirely on your particular 
circumstances : the size of the images you are handling this way, the number of 
simultaneous requests which you are handling, how much memory you have to play with, and 
how fast your CPU is.
It is sometimes surprising to make the calculation.

By writing an image first to a memory buffer, you use up the additional memory of that 
buffer, which is equal to the output size of your image, plus the overhead of the 
ByteArrayOutputStream structure.

So let's use some totally arbitrary parameters, just for the sake of an example :
- let's say that ByteArrayOutputStream has 50% overhead. So to store 250 KB of data, in 
reality uses up 375 KB of RAM
- you serve up to 100 basic browser page requests at a time (that is, the base html pages

which include the images)
- each such page contains 4 (links to) images
- each image is on average 250 KB in size (a small jpeg)
- the browsers themselves, when finding image links in a page, will issue up to 4 
simultaneous requests for those images (the last time I looked, quite a long time ago, 
browsers only requested 2 things in parallel, but they might have improved since)

So you could in theory have 400 simultaneous requests, for 400 images, each 250 KB in size.
Thus your Tomcat server (supposing it can handle 400 threads at a time) would be creating

400 instances of ByteArrayOutputStream, and
- first filling them up until they reach 250 KB of data
- then copying this data back onto the Response output stream
- then discarding the ByteArrayOutputStream

So, compared to using the Response output stream directly, you would now use an additional
(375 KB X 400) = 150,000 KB = about 150 MB additional Heap space

That seems reasonable to me.
But of course it would be a problem if you are currently running Tomcat with a 128 MB heap.
Or if your images, instead of being 250 KB on average, would be 250 MB.
Or if filling up - and reading back - the ByteArrayOutputStream was very inefficient and 
used up all your CPU time.

On the other hand, the alternative is to have broken responses, so it may be better to add

some RAM to the system.

Note: the above calculation is probably quite questionable.  But it provides a quick 
estimate, that may be roughly within a factor 10 of reality.
I use this often at the beginning of a project, to at least get an idea whether something

seems reasonable/feasible, or is totally off-kilter.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message