Fixing object lifecycle in Java bindings
At the bottom of the "Java Wrapping" page in the VTK docs, there is a section on a refactoring of the Java wrapping that happened back in 2007:
https://vtk.org/Wiki/VTK/Java_Wrapping#Java_Wrapper_Refactoring_.28Oct_8.2C_2007.29
All the problems described there, surrounding object lifecycle, have proper solutions, but the solutions adopted by VTK are not the right way to solve these problems. I haven't looked to see if this information is out of date (i.e. if the Java VTK bindings have now adopted more modern or proper solutions to the listed problems), but here is the relevant info needed to solve the problems the right way:
(1) The correct way to tie the lifecycle of C++ objects to the lifecycle of Java objects without using finalizers is to use phantom references (which works on JDK 1.2+):
http://blog.ragozin.info/2016/03/finalizers-and-references-in-java.html
(2) In JDK 9+, the phantom reference logic has been wrapped up in the Cleaner class for convenience:
https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Cleaner.html
This is really just a class that encasuplates the boilerplate phantom reference code in the first link. However, the proper usage of the Cleaner class gives other clues as to how to solve some of the other issues that VTK was facing:
http://www.enyo.de/fw/notes/java-finalization-revisited.html
Note the comments in the last link above about the use of reachabilityFence
, and synchronized
on both finalize
and close
. These directly solve the issues of the GC running while a method call (passed the last reference to the object) is executing, which was described as a problem on the VTK Java Wrapping page.
(3) To tie the lifecycle of smart pointers to Java objects, see the following:
http://www.studiofuga.com/2017/03/10/a-c-smart-pointer-wrapper-for-use-with-jni/
However, this particular code is not optimal, because the handle.h
code looks up the method id for every pointer dereference. This should be done just once per class, and held in a global reference:
http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/refs.html
By combining all of the above mechanisms, refcounted (or directly allocated) C++ objects can be bound exactly to the lifecycle of Java objects.