VTK/Java Wrapping

From KitwarePublic
< VTK
Revision as of 19:12, 18 August 2011 by Jeff (talk | contribs) (→‎Usage)
Jump to navigationJump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Configuration

You basically just need to turn VTK_WRAP_JAVA on in CMake and build.

Bartlomiej Wilkowski has created a nice tutorial of configuring Java wrapping with VTK.

Mac (Snow Leopard)

To build a sample application provided in VTK against your VTK build directory (with an installed VTK replace "bin" with "lib"):

$ export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:your_vtk_build_dir/bin
$ javac -cp your_vtk_build_dir/bin/vtk.jar your_vtk_source_dir/Wrapping/Java/vtk/sample/Demo.java
$ java -cp your_vtk_build_dir/bin/vtk.jar:your_vtk_source_dir/Wrapping/Java vtk.sample.Demo

Sample Code (from VTK/Wrapping/Java/vtk/sample/SimpleVTK.java)

<source lang="java"> /**

* An application that displays a 3D cone. The button allow to close the
* application
*/

public class SimpleVTK extends JPanel implements ActionListener {

   private static final long serialVersionUID = 1L;
   private vtkPanel renWin;
   private JButton exitButton;
   // -----------------------------------------------------------------
   // Load VTK library and print which library was not properly loaded
   static {
       if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
           for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
               if (!lib.IsLoaded()) {
                   System.out.println(lib.GetLibraryName() + " not loaded");
               }
           }
       }
       vtkNativeLibrary.DisableOutputWindow(null);
   }
   // -----------------------------------------------------------------
   public SimpleVTK() {
       super(new BorderLayout());
       // build VTK Pipeline
       vtkConeSource cone = new vtkConeSource();
       cone.SetResolution(8);
       vtkPolyDataMapper coneMapper = new vtkPolyDataMapper();
       coneMapper.SetInputConnection(cone.GetOutputPort());
       vtkActor coneActor = new vtkActor();
       coneActor.SetMapper(coneMapper);
       renWin = new vtkPanel();
       renWin.GetRenderer().AddActor(coneActor);
       // Add Java UI components
       exitButton = new JButton("Exit");
       exitButton.addActionListener(this);
       add(renWin, BorderLayout.CENTER);
       add(exitButton, BorderLayout.SOUTH);
   }
   /** An ActionListener that listens to the button. */
   public void actionPerformed(ActionEvent e) {
       if (e.getSource().equals(exitButton)) {
           System.exit(0);
       }
   }
   public static void main(String s[]) {
       SwingUtilities.invokeLater(new Runnable() {
           @Override
           public void run() {
               JFrame frame = new JFrame("SimpleVTK");
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.getContentPane().setLayout(new BorderLayout());
               frame.getContentPane().add(new SimpleVTK(), BorderLayout.CENTER);
               frame.setSize(400, 400);
               frame.setLocationRelativeTo(null);
               frame.setVisible(true);
           }
       });
   }

} </source>

Java Wrapper Refactoring (Oct 8, 2007)

There were a few problems with the old Java wrappers. One was that, as you said, objects were being deleted before they were supposed to. We hacked in a fix at one point about a year ago which basically made all VTK objects accessed from Java stay around forever, but this was not acceptable either.

Ref:

The other major concern was that the map from Java objects to VTK objects was in the C++ JNI layer, and while we tried to keep this map synchronized with a mutex, race conditions could still occur because other Java threads could advance while the JNI layer was being called (a thread could access a C++ object just as it is being garbage-collected and deleted). There does not seem to be a way to atomically call a JNI method, or ensure the collector doesn't run while a method is called. This second issue forced us to rethink how the map is done, and the solution was to keep the map in Java instead of C++. But we didn't want this Java map to prohibit objects from being garbage collected. Fortunately, Java has a WeakReference class for just this type of purpose. When accessed, the reference will either be valid or null depending on whether it has been garbage-collected.

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/WeakReference.html

Thus, the wrapper code can lookup objects in this map when returning objects from methods, and if it is not there, or null, it creates a new Java object representing that C++ object.

A final issue was that we wanted a way to guarantee all C++ destructors are called before the program exits. The natural place to decrement the reference count of the C++ object is in finalize(), which works when things are garbage-collected, but Java does not guarantee that finalize will ever be called. So the method vtkGlobalJavaHash.DeleteAll() will plow through the remaining VTK objects and call Delete on them.