Hi there,

while hunting down a memory leak (it turned out that some servlets
didn't release PageContexts after use) I came across some places in
tomcat which are a bit memory inefficent.

(I'm talking about Tomcat 5.5 SVN as of tuesday or yesterday.)

The root cause (but not the problem) is that PageContexts are pooled in
JspFactoryImpl. The first interesting spot is the BodyContentImpl[] outs
member of PageContextImpl. It will only grow over time and it will never
release the BodyContentImpls stored in there. As PageContexts are
pooled, a single PageContext instance gets used by a lot of different
JSPs (possibly all JSPs present in the app).

The next interesting spot is the char[] cb member of BodyContentImpl it
will also only grow over time and never release the space occupied by
the buffer.

Let's consider a JSP with a single BodyTag which will buffer a
significant amount of data (say 1 MB). Over time, all
PageContextImpls.out[0].cb-s will grow to this size. The
JspFactoryImpl's PageContext pool contains up to 100 PageContexts, so I
may end up with 100 MB of memory which is basically unused.

I patched Tomcat to re-initialize PageContextImpl.outs on release().
This should increase memory efficiency significantly.

Second, I re-initialized BodyContentImpl.cb[] on clear() - this seems
superfluous but I found tags in the pools which still held
BodyContentImpls as bodyContent therefore possibly locking lots of
memory. Third, I let JspWriterImpl null it's cb on recycle() since I
also found some of these lingering around and still holding parts of the
output. The last two steps might be unneccessary if we could prevent
that tags in the pools still hold BodyContents (as far as
BodyTagSupport.bodyContent is involved).

What do you think about this issue?

Bye, Tino.

PS: Proposed patch attached.

Index: src/share/org/apache/jasper/runtime/PageContextImpl.java
===================================================================
--- src/share/org/apache/jasper/runtime/PageContextImpl.java    (revision 
356603)
+++ src/share/org/apache/jasper/runtime/PageContextImpl.java    (working copy)
@@ -203,7 +203,8 @@
        autoFlush = true;
        request = null;
        response = null;
-        depth = -1;
+    outs = new BodyContentImpl[0];
+    depth = -1;
        baseOut.recycle();
        session = null;
 
@@ -706,9 +707,7 @@
         depth++;
         if (depth >= outs.length) {
             BodyContentImpl[] newOuts = new BodyContentImpl[depth + 1];
-            for (int i=0; i<outs.length; i++) {
-                newOuts[i] = outs[i];
-            }
+            System.arraycopy(outs, 0, newOuts, 0, outs.length);
             newOuts[depth] = new BodyContentImpl(out);
             outs = newOuts;
         }
Index: src/share/org/apache/jasper/runtime/BodyContentImpl.java
===================================================================
--- src/share/org/apache/jasper/runtime/BodyContentImpl.java    (revision 
356603)
+++ src/share/org/apache/jasper/runtime/BodyContentImpl.java    (working copy)
@@ -468,6 +468,9 @@
             throw new IOException();
         } else {
             nextChar = 0;
+            // dispose old buffer since it might have become HUGE
+            bufferSize = Constants.DEFAULT_TAG_BUFFER_SIZE;
+            cb = new char[bufferSize];
         }
     }
     
Index: src/share/org/apache/jasper/runtime/JspWriterImpl.java
===================================================================
--- src/share/org/apache/jasper/runtime/JspWriterImpl.java      (revision 
356603)
+++ src/share/org/apache/jasper/runtime/JspWriterImpl.java      (working copy)
@@ -98,6 +98,7 @@
         flushed = false;
         closed = false;
         out = null;
+        cb = null;
         nextChar = 0;
         response = null;
     }

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to