Mapscript API: for object manipulation, not object creation?
Rick Innis
rick at INNIS.CA
Mon May 30 10:15:21 PDT 2005
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 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.
Here's what I think is happening:
- I load a map from a mapfile
- in Java, I get the corresponding instance of mapObj - basically a
wrapper for the C structure.
- I create a new layerObj in Java - again a wrapper for the
corresponding C structure. Behind the scenes (in C) this is
associated with the C mapObj.
- I create a classObj and a styleObj - again, C structs behind the
scenes
- my application does its thing
- the objects go out of scope
- eventually, the Java GC kicks in
- when the Java mapObj is gc'd, the finalizer is invoked. This calls
the delete_<foo>Obj method, which calls into mapserver to deallocate
the memory for the corresponding C struct. This also deallocates
anything it has a reference to, including the memory for the
layerObj, classObj and styleObj I created.
- Java then tries to gc the other objects, which includes trying to
free their memory - which has already been freed. Result: segment
violation
Does this make sense to people? From work that I know others have
done in Perl, it seems that everything you need in a map is best
declared in the mapfile, and the API can be used to manipulate that,
but creating and manipulating new objects via the API is problematic.
--Rick.
More information about the MapServer-users
mailing list