[vtkusers] VTK/Java crashes -- WeakGlobalRef or garbage collection problem?

Eran Guendelman erang at stanford.edu
Mon Jun 18 03:59:12 EDT 2007


We're getting very weird crashes using VTK with Java wrappings.  They're
  weird because they occur at random times during the execution of our
program, but when run long enough they always do seem to eventually
occur (e.g. after 2-5 minutes).  My main approach to getting it to crash
  is to start the animation in our application, the animation makes lots
of calls to functions such as these

public void setNormalAtLocation(int index, double x, double y, double z) {
	vtkPointData t = pointPolyData.GetPointData();
         vtkDataArray u = t.GetNormals();
         u.SetTuple3(index, x, y, z);
}

and

public void setTensorDataAtLocation(int index, double xx, double xy,
double xz, double yx, double yy, double yz, double zx, double zy, double zz)
{
         vtkPointData t = pointPolyData.GetPointData();
         t.GetTensors().SetTuple9(index, xx, xy, xz, yx, yy, yz, zx, zy,
zz);
}

and the crash typically occurs inside one of these functions.
pointPolyData is a class member of type vtkPolyData.
methods exist.

I've #defined VTKJAVADEBUG when compiling the (debug) VTK libraries, and
also added other print statements for my own debugging use, and by
examining the output I've started to see a pattern in what seems to be
causing the crash.  Basically, there are two threads that are calling
down to VTK C++ calls... these are the main event thread, and the
finalizer thread which does garbage collection.  What seems to be
happening is that in a call such as

	vtkPointData t = pointPolyData.GetPointData();
         vtkDataArray u = t.GetNormals();

when the GetNormals is getting processed in the C++ side, for some
reason the garbage collector seems to think that t can be deallocated,
and the finalizer deletes it from under the feet of the main event
thread which expects it to exist... so e.g. we have something like

t.GetNormals()
	causes the execution of
Java_vtk_vtkDataSetAttributes_GetNormals_120
	which calls
vtkJavaGetPointerFromObject
	which calls vtkJavaGetId and gets a valid id for the object, but then
gets ptr = 0 and command = 0 for that object because in the meantime the
garbage collector has called vtkJavaDeleteObject which deleted it from
the hash table

	So now back in
Java_vtk_vtkDataSetAttributes_GetNormals_120
	it receives a NULL pointer, but assumes it's not NULL and calls
(op)->GetNormals()
	causing a crash!

Anyway, in vtkJavaUtil.cxx I found that weak global references were used
(NewWeakGlobalRef and DeleteWeakGlobalRef called, at least for
JNI_VERSION_1_2 and up which is the case in our install).  Admittedly I
don't know much about these creatures, but looking online I found a
comment in http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html
saying that weak global references are dangerous because they don't
count as a real reference as far as garbage collection is concerned, and
the type of potential problem mentioned in this document sounded very
similar to what we are experiencing (objects getting garbage collected
during call to native method).  So I tried changing to non-weak global
refs (NewGlobalRef and DeleteGlobalRef), and indeed found that our
crashes seemed to stop (by which I mean I ran it for 10 minutes without
crashing which never happened before...  doesn't conclusively mean the
crash is fixed, but seems to be a positive change).


So has anyone else experienced a similar problem?  Anyone know whether
the use of weak global references by VTK/Java is indeed a mistake, or
should they be working and we just have some other problem with our code?

Any help would be greatly appreciated,

Eran.





More information about the vtkusers mailing list