xml-rpc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Rall <...@finemaltcoding.com>
Subject Re: CDATA leaks in XmlRpc client classes
Date Mon, 11 Nov 2002 22:49:59 GMT
"Glen Lewis" <glewis@lspeed.com> writes:

> XmlRpc.parse() initializes the "cdata" field and then clears it ( by
> calling setLength(0) ) upon subsequent calls to parse().  This
> results in a memory leak between calls to parse(), since the "cdata"
> field persists as long as the XmlRpc object.  In my particular case,
> a large logfile was being passed as a parameter in a response, and
> the "cdata" leak was many megs in size - it ended up consuming all
> the memory available to my client application.
> 
> I fixed it (somewhat aggressively) by changing the line in
> XmlRpc.java that reads:
>
> 		parser.parse (new InputSource (is));
> to:
> 		try
> 		{
> 			parser.parse (new InputSource (is));
> 		}
> 		finally
> 		{
> 			cdata = null;
> 		}

Hey Glen.  What you describe is definitely a problem.  Releasing the
buffer every time doesn't seem like the Right solution either, since
if it is used once it's very likely to be used again.  Setting a
"resource release threshold" of, say, 4 times the the original
allocation seems like reasonable behavior.  What do you say to this
patch?


Index: XmlRpc.java
===================================================================
RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
retrieving revision 1.33
diff -u -u -r1.33 XmlRpc.java
--- XmlRpc.java	10 Oct 2002 00:33:24 -0000	1.33
+++ XmlRpc.java	11 Nov 2002 22:47:33 -0000
@@ -414,7 +414,20 @@
         {
             System.out.println("Beginning parsing XML input stream");
         }
-        parser.parse(new InputSource (is));
+        try
+        {
+            parser.parse(new InputSource (is));
+        }
+        finally
+        {
+            // Clear any huge buffers.
+            if (cdata.length() > 128 * 4)
+            {
+                // Exceeded original capacity by greater than 4x; release
+                // buffer to prevent leakage.
+                cdata = null;
+            }
+        }
         if (debug)
         {
             System.out.println ("Spent " + (System.currentTimeMillis() - now)


Some sort of StringBuffer pool might make for a better long-term
solution, but this ought to fix the immediate problem.
-- 

Daniel Rall <dlr@finemaltcoding.com>

Mime
View raw message