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

David Marshburn marshbur at cs.unc.edu
Mon Jun 18 18:16:48 EDT 2007


------------------------------

> Message: 5
> Date: Mon, 18 Jun 2007 00:59:12 -0700
> From: Eran Guendelman <erang at stanford.edu>
> Subject: [vtkusers] VTK/Java crashes -- WeakGlobalRef or garbage
> 	collection	problem?
> To: vtkusers at vtk.org
> Message-ID: <46763B50.8010801 at stanford.edu>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed

<snip>

> 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?

hi eran,

yes, we've seen similar problems.  we've also seen it when we have a chain 
of Get* like you describe.  it does happen seemingly randomly; it is a 
race condition between your code and the garbage collector (that said, i 
haven't written a simple example exhibiting this behavior).

from the java language specification, 3d ed.
http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.6.1
"A reachable object is any object that can be accessed in any potential 
continuing computation from any live thread. Optimizing transformations of 
a program can be designed that reduce the number of objects that are 
reachable to be less than those which would naively be considered 
reachable. For example, a compiler or code generator may choose to set a 
variable or parameter that will no longer be used to null to cause the 
storage for such an object to be potentially reclaimable sooner."

one thing you can do to see if this is really the problem is to add dummy 
references to all the variables later in your functions, like the code 
below.  you could also try explicitly adding Register and Delete calls to 
all the variables in the method.

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);
	u.DoSomethingIdempotent();
	t.DoSomethingIdempotent();
}

(as an aside, no, these aren't solutions to the problem because it's not 
reasonable to add such code to every method in order to control the 
garbage collector).


global references might be the answer, but the corresponding problems is 
that they can lead to objects never being finalized and the memory 
reclaimed.  i looked at this a couple of years ago, and i have a vague 
recollection that i didn't want to use global references, but i don't 
remember why.  i would like to think that they could be used in an unleaky 
way, but it would require showing that both vtk and java wouldn't be 
waiting on the other one to first reduce the reference count.

i think the problem may be the following:  there are two ways a java-based 
vtk object can come into existence.  1) created with the new operator in 
java (which eventually calls the native contructor and store a mapping 
between the corresponding java and native objects), or 2) accessed as the 
member of some other object, through a call to Get*.  in case 2), the vtk 
native code is invoking the new operator in java and storing the mapping 
between the two objects.  in both cases, a weak global reference is 
created for the java object, representing the continued desire for the 
native vtk code to be able to refer to the java object, and a vtk 
reference is made, representing the fact that the java wrapper, at least, 
wants to continue to refer to the native vtk object.  with a strong 
reference, the problem is that then neither vtk nor java can say "i'm done 
with this object" because of the extra (circular) reference.  the java 
reference is global (hence always recheable) and never garbage- 
collectable/reclaimable until program termination).  and the vtk reference 
exists until java says it's done with the java object.  using a weak 
reference lets the objects be garbage-collected, but sometimes too early.

i'd like to see a solution to this make its way into vtk, and i'd be glad 
to continue thinking/talking/working on it.


-david







More information about the vtkusers mailing list