[vtkusers] Re: VTK/Java crashes -- WeakGlobalRef or garbage collection problem?
Eran Guendelman
erang at stanford.edu
Mon Jun 18 18:42:30 EDT 2007
Thanks for all of your responses. Somewhat reassuring to see that we're
not the only ones experiencing this problem, but very troubling that
this has never been addressed by kitware. Are there not many people
using VTK with Java? Are they not getting these mysterious crashes?
(Maybe it's worse because we're doing animation which makes lots of
frequent calls to update the vtk objects, thus increasing the chance
that the race condition will fail).
I just wanted to add that SWIG (used to create Java wrapping of C++
code) also discusses this issue in their documentation. In
http://www.swig.org/Doc1.3/Java.html
search for "premature". e.g. they write
You may notice that SWIG uses a Java long wherever a pointer or class
object needs to be marshalled across the Java-C/C++ boundary. This
approach leads to minimal JNI code which makes for better performance as
JNI code involves a lot of string manipulation. SWIG favours generating
Java code over JNI code as Java code is compiled into byte code and
avoids the costly string operations needed in JNI code. This approach
has a downside though as the proxy class might get collected before the
native method has completed. You might notice above that there is an
additional parameters with a underscore postfix, eg jarg1_. These are
added in order to prevent premature garbage collection when marshalling
proxy classes.
and in
http://www.swig.org/Doc1.3/Java.html#java_memory_management_member_variables
they describe a technique to avoid premature garbage collection when
returning references to member variables -- essentially adding an extra
reference to the object to avoid a delete. (Maybe this is more similar
to case (2) you describe below).
I've run the program many more times now using strong (non-weak)
references without crashing (and then put it back to weak references and
got it consistently crashing within a few minutes of execution). So I'm
very confident that this was the problem... But if strong references
are going to eat up memory without deallocation then this is also not a
good solution.
We've now actually been thinking of converting some of our Java code to
C++, so we might be able to reduce the problem. We have lots of java
code that calls down to vtk to update the various vtk objects in the
scene, but we're thinking of grouping all that stuff together and
writing it in C++ (and calling that C++ function from java)... hopefully
we'll get better performance this way, too, since calling vtk from java
has overhead as we see in vtkJavaUtil.cxx (even string comparisons for
the type casting!).
Thanks.
David Marshburn wrote:
> ------------------------------
>
>> 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
>
>
>
>
> _______________________________________________
> This is the private VTK discussion list.
> Please keep messages on-topic. Check the FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers
>
More information about the vtkusers
mailing list