Antwort: Re: [MAPSERVER-USERS] leaking memory in java mapscript (was Re: thread safety)

umn-ms at hydrotec.de umn-ms at hydrotec.de
Thu Feb 21 02:36:54 EST 2008


Hi

> I don't totally understand how all of the SWIG stuff works, but I can 
follow
> it a bit.  The source for this is:
It's easier to watch the SWIG-generated JNI-Code in 
mapscript/java/mapscript_wrap.c 
Example: 
  mapscriptJNI.delete_imageObj(swigCPtr);
is implemented by the C-function
  SWIGEXPORT jbyteArray JNICALL 
Java_edu_umn_gis_mapscript_mapscriptJNI_imageObj_1getBytes 

> confirm that the caller must free the returned array (with gdFree()).
At the end of the long-named C-function you'll find a call to gdFree

Can you estimate how much memory is lost in each step of your
testprogram? Is it approx. the size of the image?

Benedikt Rothe


mapserver-users-bounces at lists.osgeo.org schrieb am 21.02.2008 03:31:09:

> 
> 
> rich.fromm wrote:
> > 
> > Other than calling delete() on every mapserver object as applicable, 
is
> > there
> > anything else that I can be doing?  I fear that there may be a real
> > genuine
> > leak within mapserver, and that that might be hard to track down.
> > 
> 
> I have narrowed this down to a smaller testcase, that only has two 
mapscript
> objects.
> 
> I have a fixed map file, and I'm doing barely anything, just creating 
the
> map
> object from the map file, drawing to the image object, and getting the
> bytes.
> I am calling both map.delete() and img.delete() at the end.  Then I loop
> over
> all of this repeatedly.
> 
> This is a little bit of a simplification, but essentially what I'm doing 
is
> this:
> 
>       for (int i = 0; i < loop; i++) {
>          mapObj map = null;
>          imageObj img = null;
> 
>          try {
>             map = new mapObj(filename);
>             img = map.draw();
>             byte[] bytes = img.getBytes();
>          } catch (Exception e) {
>             System.err.println("Caught exception: " + e);
>             e.printStackTrace(System.err);
>          } finally {
>             if (img != null) {
>                img.delete();
>             }
>             if (map != null) {
>                map.delete();
>             }
>          }
>          System.gc();
>       } // end for
> 
> I have tried a number of variants of this (including outputting the 
bytes to
> a
> file), and the offending line seems to be the call to 
imageObj.getBytes().
> With it, my program leaks.  Without it, it does not:
> 
> [rich at peyote mapserver_test 17:53:31]$ <mapserver_test> diff -u
> java/src/TestMapscript.java.bak1 java/src/TestMapscript.java.bak3
> --- java/src/TestMapscript.java.bak1   2008-02-20 17:37:43.000000000 
-0800
> +++ java/src/TestMapscript.java.bak3   2008-02-20 17:53:27.000000000 
-0800
> @@ -1,4 +1,4 @@
> -// this code does NOT leak
> +// this code DOES leak
> 
>  import edu.umn.gis.mapscript.mapObj;
>  import edu.umn.gis.mapscript.imageObj;
> @@ -47,7 +47,7 @@
>              System.err.println("Drawing map to image object");
>              img = map.draw();
> 
> -//             byte[] bytes = img.getBytes();
> +            byte[] bytes = img.getBytes();
>  //             int width = img.getWidth();
>  //             int height = img.getHeight();
>  //             System.err.println("The image is of size " + width + " x 
" +
> height + " and contains " + bytes.length + " bytes");
> [rich at peyote mapserver_test 17:53:53]$ <mapserver_test> 
> 
> I am calling System.gc() at the end of each iteration.  And by examining 
the
> memory from java's perspective (Runtime.getRuntime().freeMemory() and
> Runtime.getRuntime().totalMemory()) I can see that it is reasonably 
stable.
> However, the memory as reported by top gradually grows.
> 
> The source for imageObj.getBytes() is as follows:
> 
> mapscript/java/edu/umn/gis/mapscript/imageObj.java
> 
>   public byte[] getBytes() {
>     return mapscriptJNI.imageObj_getBytes(swigCPtr);
>   }
> 
> I don't totally understand how all of the SWIG stuff works, but I can 
follow
> it a bit.  The source for this is:
> 
>   getBytes() (mapscript/swiginc/image.i)
> 
> which notes the following:
> 
>     /*
> 
> 
-------------------------------------------------------------------------
>     getBytes returns a gdBuffer structure (defined in mapscript.i) which
> must
>     be typemapped to an object appropriate to the target language.  This
>     typemap must also gdFree the data member of the gdBuffer.  See the 
type-
>     maps in java/javamodule.i and python/pymodule.i for examples.
> 
>     contributed by Jerry Pisk, jerry.pisk at gmail.com
> 
> 
-------------------------------------------------------------------------
>     */
> 
> And all of the following:
> 
>   msSaveImageBuffer() (maputil.c)
>   msSaveImageBufferAGG() (mapagg.cpp)
>   msSaveImageBufferGD() (mapgd.c)
> 
> confirm that the caller must free the returned array (with gdFree()).
> 
> What's not entirely clear to me is whether "the caller" means the java
> mapscript code, or the application writer.  In other words, am I 
responsible
> for doing this, or should this happen when I call img.delete() ?  Here 
is
> the
> code for imageObj.delete():
> 
> mapscript/java/edu/umn/gis/mapscript/imageObj.java
> 
>   public void delete() {
>     if(swigCPtr != 0 && swigCMemOwn) {
>       swigCMemOwn = false;
>       mapscriptJNI.delete_imageObj(swigCPtr);
>     }
>     swigCPtr = 0;
>   }
> 
> But even though I don't see a call to gdFree() there, it's not clear to 
me
> that it's not happening somewhere.  I don't understand the SWIG path 
enough,
> and I haven't yet tried following it in gdb.  (Although that might be 
worth
> trying.)
> 
> If I am responsible for doing this, how do I do it?  It appears to me 
that
> gdFree() is not part of the mapscript API (it doesn't appear in the 
docs),
> and
> just that it is just a mapscript internal function.
> 
> Right now my test case is using a fairly complicated mapfile from a 
large
> data
> source located in a postgis database.  I will try to see if I can 
replicate
> this problem with a simpler map file and/or synthetic data.
> 
> But in the mean time I wanted to post this in case anyone might have 
some
> advice based on these observations.
> 
> Once again, thanks for any help that anyone might be able to provide.
> 
> - Rich
> 
> p.s. This is all based on mapserver 5.0.0
> 
> -- 
> View this message in context: http://www.nabble.com/thread-safety-
> tp15514019p15603603.html
> Sent from the Mapserver - User mailing list archive at Nabble.com.
> 
> _______________________________________________
> mapserver-users mailing list
> mapserver-users at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/mapserver-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/mapserver-users/attachments/20080221/fd0b46e8/attachment.html


More information about the mapserver-users mailing list