Mapscript API: for object manipulation, not object creation?

Sean Gillies sgillies at FRII.COM
Mon May 30 14:08:37 EDT 2005


Hi Rick, comments interleaved below ...

On May 30, 2005, at 11:15 AM, Rick Innis wrote:

> Would I be right in thinking that the primary purpose of the
> MapScript API is to manipulate properties of a map defined in a
> mapfile, rather than to programatically create a map or map elements
> using the API?
>

The mapscript API is a product of evolution rather than design, and so
it has many purposes ;) I have done a lot of work since version 4.2 to
make sure that it does support programatic creation of map elements.
I'm testing it rigorously with Python, but not with Java.

> The reason I ask this is that I'm trying to define a layer
> dynamically using the Java version of the SWIG API, and I'm running
> into what appears to be a garbage collection issue. (I've replicated
> the same issue on both Linux (Debian "sarge", 2.6.8 kernel) and Mac
> OS X 10.4.1, so I'm reasonably confident it's not a platform-specific
> issue.)
>
> Here's a code fragment to illustrate what I'm doing, which is
> basically creating a layer, class, and style object and adding the
> layer to a map that was previously read in from a mapfile:
>
>                  layerObj l = new layerObj(map);
>                  l.setType(MS_LAYER_TYPE.MS_LAYER_POINT);
>                  l.setConnectiontype(MS_CONNECTION_TYPE.MS_POSTGIS);
>                  String connectionString  = "...";
>
>                  l.setConnection(connectionString);
>                  l.setData("shape from sometable");
>
>                  l.setStatus(mapscriptConstants.MS_ON);
>                  l.setName("data_layer");
>                  classObj c = l.getClass(0);
>                  if (c == null) c = new classObj(l);
>                  c.setStatus(mapscriptConstants.MS_ON);
>                  styleObj style = new styleObj(c);
>                  style.setBackgroundcolor(map.getImagecolor());
>                  style.setSymbol(1);
>                  style.setSymbolname("pin");

> This is working OK - the layer is displayed and look as I expect it
> to. However, after a few loads of the map I'm getting errors when
> Java runs its garbage collection:
>
> An unexpected exception has been detected in native code outside the
> VM.
> Unexpected Signal : 11 occurred at PC=0x4E9D4EFA
> Function=(null)+0x4E9D4EFA
> Library=/usr/local/lib/libmapscript.so
>
> NOTE: We are unable to locate the function name symbol for the error
>        just occurred. Please refer to release documentation for
> possible
>        reason and solutions.
>
> Current Java thread:
>          at edu.umn.gis.mapscript.mapscriptJNI.delete_classObj(Native
> Method)
>          at edu.umn.gis.mapscript.classObj.delete(classObj.java:35)
>          at edu.umn.gis.mapscript.classObj.finalize(classObj.java:29)
>          at java.lang.ref.Finalizer.invokeFinalizeMethod(Native Method)
>          at java.lang.ref.Finalizer.runFinalizer(Finalizer.java:83)
>          at java.lang.ref.Finalizer.access$100(Finalizer.java:14)
>          at java.lang.ref.Finalizer$FinalizerThread.run
> (Finalizer.java:160)
>
> (The method at the top of the execution stack might also be
> delete_layerObj; I've seen both.)
>
> After looking into mapscript_wrap.c my theory is that what's
> happening is that Java is trying to deallocate an object that's
> already been deallocated on the C side of the world.
>

Right. There may be a bug in the one argument forms of classObj and
layerObj constructors that does not properly transfer ownership of the
object to its parent. In the meanwhile, the solution is for you to
begin using the current configuration API, the documentation is
distributed with mapscript under mapscript/docs/mapfile-HOWTO.txt and
online at

   http://zcologia.com/mapserver/mapfile-howto

Once you replace the old-style usage (example)

   layerObj l = new layerObj(map);
   l.setName('new_layer');
   ...

with the current (using the zero argument constructors)

   layerObj new_layer = new layerObj();
   new_layer.setName('new_layer');
   ...
   li = map.insertLayer(new_layer);
   l = map.getLayer(li);

the garbage collection problem is avoided. In a nutshell, the current
way of building up a map configuration is to create an element (layer,
class, or style), configure it, and then insert a *copy* of it into a
parent container. The insert* methods transfer ownership (and
responsibility for deletion) to the parent.

cheers,
Sean

--
Sean Gillies
sgillies at frii dot com
http://zcologia.com



More information about the mapserver-users mailing list