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