Building VTK on Linux with Java support

This document details my experiences, frustrations, and ultimate success in building VTK 4.0 on RedHat Linux 8.0 with support for Sun's Java Developement Kit 1.4.1_01. It was written Jan 21, 2003; things have probably changed since I wrote it. I am not affiliated with Kitware or the VTK project in any way, use this information at your own risk, there is no guarantee or warranty, your mileage may vary, etc., etc.

Update! (20 Mar 2003)

Bas van der Linden figured out the mystery of the non-relocatable libraries. I haven't yet recompiled VTK myself to verify his findings, so I'll just include them here in original form:

I've used CMake myself for some C++ projects, and know it uses the -rdynamic flag for linking. This is handy if you're developing shared libraries, because you don't need to set LD_LIBRARY_PATHs all the time, because the locations are encoded in the executable or library. This is also what caused the problem: Java finds the libs in the LD_LIBRARY_PATH, but those libs have the location of their dependencies hardcoded inside them. So, it happens a library is loaded twice and all problems start to happen.

The solution is simple. Using ccmake, toggle expert mode (by pressing t) and switch the CMAKE_SKIP_RPATH to ON. Recompile. Wait. Wait. Wait. (C++ takes way too long to compile...) Now, you're able to move your libraries wherever you want.

I hope this can complete your VTK/Java/Linux HOWTO. Maybe, one more tip. You don't have to switch BUILD_SHARED_LIBS to ON: if you leave it off, the libvtk*Java.so libraries will be self contained. The total size will be smaller (you might want to strip them anyway) than having both the C++ lib and Java wrapper lib seperately. (I'm using Debian unstable and VTK is in the distribution, except for the Java wrappers, so I do not want an extra set of C++ libs, nor do I want to recompile my Java wrapper libs when Debian moves to a newer version.)

Download and install CMake

Instructions are available on the VTK website. Also, make sure it's on your path.

In bash: export PATH=/path/to/cmake/bin:$PATH
In csh: setenv PATH /path/to/cmake/bin:$PATH

Download and install Java

I used Sun's JDK 1.4.1_01, the newest release available at the time of this writing. It was installed in /usr/local/j2sdk1.4.1_01, with a symlink to /usr/local/java. However, CMake isn't too smart, and in order for it to find your installation of Java, you need to make a symlink from /usr/local/lib/java to your JDK directory.

As root: ln -s /usr/local/j2sdk1.4.1_01 /usr/local/lib/java

Download and unpack the VTK source code

I'll assume you're doing all this from your home directory. It matters which version of the code you use: I was unable to find success with the standard, "stable" 4.0 release. Instead, I downloaded and compiled the nightly release. If there's a newer stable release, you may be able to use that; otherwise, I recommend the nightly releases. Check the quality dashboard first, as the VTK site recommends.

Configure the VTK build

From ~/VTK, run ccmake. This will give you a ncurses text GUI for configuring the build options. You'll need to turn BUILD_SHARED_LIBS, VTK_USE_ANSI_STDLIB, and VTK_WRAP_JAVA to ON. Adjust other options as needed; adjust advanced options at your own risk. Press 'c' a few times until it offers you the option to press 'g' for generate and exit. You might toggle display of the advanced options on to make sure CMake found the correct paths to the headers and shared libraries that are part of your Java install (if you made the symlink to /usr/local/lib/java, it should have). Press 'g' and then you're ready to build. (See the update for better suggestions on the configuration options to choose.)

Build VTK

Just type make from ~/VTK. This takes ~ 2 hours on my PIII laptop. If you're lucky, it will build the Java JAR file for you, too. If you're unlucky, it won't.

You don't need to do a make install; you'll use the libraries directly from the bin directory. Something bad happens to the libraries when you do a make install, and they no longer work. (See the update for a solution to this problem.)

Build the JAR

If you're lucky, this has already been done for you by make, and there's a file called vtk.jar in ~/VTK/bin. If not, do the following from ~/VTK:

Prepare your environment

You need to make sure that your newly built VTK libraries (libvtk___.so) can be found by the dynamic linker, so you have to put their location on your LD_LIBRARY_PATH.

In bash: export LD_LIBRARY_PATH=~/VTK/bin:$LD_LIBRARY_PATH
In csh: setenv LD_LIBRARY_PATH ~/VTK/bin:$LD_LIBRARY_PATH

You may want to add this to one of your shell startup scripts so that you don't have to do this every time you log in.

I thought I was able to successfully relocate these libraries using cp -a ~/VTK/bin ~/devel/vtklibs, but I have been unable to make it work again. Trying to relocate the libraries, either with make install or by hand, results in this error at runtime. This also means they cannot be installed in a typical location, like /usr/lib or /usr/local/lib. (It's possible to get around this; see the update.)

You also have to make sure that Java can find vtk.jar. You can do this by putting it on your CLASSPATH, by using the -cp or -classpath switches on the command line, or by putting it in your installed extensions directory (something like /usr/local/java/jre/lib/ext). It's your choice; I use the command line switches in my Makefiles (for both javac and java).

Run a test program

I'd recommend using the first part of the tutorial. Do this:

cd Examples/Tutorial/Step1/Java/
javac -classpath ../../../../bin/vtk.jar Cone.java
java -classpath ../../../../bin/vtk.jar:. Cone

Errors and troubleshooting

An unexpected exception has been detected in native code outside the VM.
Unexpected Signal : 11 occurred at PC=0x4CA7D87C
Function=_ZN12vtkHashTable12AddHashEntryEPvS0_+0x52
Library=/home/ian/devel/vtklib/libvtkCommonJava.so

Current Java thread:
        at vtk.vtkPolyData.VTKCastInit(Native Method)
        at vtk.vtkPolyDataSource.GetOutput_2(Native Method)
        at vtk.vtkPolyDataSource.GetOutput(vtkPolyDataSource.java:20)
        at vtkprogs.SphereTest.Main(SphereTest.java:78)
        at vtkprogs.SphereTest.main(SphereTest.java:162)

Dynamic libraries:
...
4c9d2000-4ca88000 r-xp 00000000 03:07 786156     /home/ian/devel/vtklib/libvtkCommonJava.so
4ca88000-4cab1000 rw-p 000b6000 03:07 786156     /home/ian/devel/vtklib/libvtkCommonJava.so
...
4cdb8000-4ce6e000 r-xp 00000000 03:07 262765     /home/ian/tmp/VTK/bin/libvtkCommonJava.so
4ce6e000-4ce97000 rw-p 000b6000 03:07 262765     /home/ian/tmp/VTK/bin/libvtkCommonJava.so
...


This sort of error appears to be caused by relocating the libraries; the linker appears to try to load them both from where they were built and from where they were copied to. See the update for a possible solution to this problem. Otherwise, make sure you're using the libraries in-place, where they were compiled and built by make.

Cone.java:9: package vtk does not exist
import vtk.*;
^
Cone.java:33: cannot resolve symbol
symbol  : class vtkConeSource
location: class Cone
    vtkConeSource cone = new vtkConeSource();
    ^

You've left vtk.jar off of your classpath during compilation.
Exception in thread "main" java.lang.NoClassDefFoundError: Cone

You've left the current direcory off of your classpath during execution. This is the reason for the extra colon and dot in the command line above.

Exception in thread "main" java.lang.NoClassDefFoundError: vtk/vtkMapper

You've left vtk.jar off of your classpath during execution.