Fun with native libs (1): Java3D
Motivation
An important part in the field of scientific visualization is the display of 3 dimensional geometric data. One option for Java developers to get this task done is to use the Java3D API (another one would be to OpenGL for Java bindings, like done in the JCanyon demo for the JDK 1.4 beta).
At the time of this writing (JDK 1.4 is beta), the Java3D API is not part of the standard Java JRE.
Usually, people who want to run a Java3D enabled Java program have to download and install the seperatly available Java3D installation files for their specific plattform themselves.
This would obviously ruin the goal of one click installation for someone who is interested to run the app but had not installed Java3D before.
Ideally for Web Start deployment purposes, Sun would have packed and signed Java3D in some nice jars. But it hasn't yet. (But they promised)
So one needs to do it oneself.
A first solution
The first working solution to this problem I noticed was by Dr. Masa Takatsuka in this thread
http://forums.java.sun.com/thread.jsp?forum=38&thread=71532
He works on an interesting application called JBeanStudio that features 3D data viewers
http://www.geovistastudio.psu.edu/JBeanStudio
and managed to deploy the necessary Java3D libs together with the application via Web Start.
Looking at the jnlp file he published, his approach was first to seperate all Java3D stuff into its own sub jnlp file:
<extension name="Java3D" href="lib/core/Java3D/Java3D.jnlp"/>
In that sub jnlp file he used this division of resources for the different platforms:
<resources>
<jar href="j3daudio.jar"/>
<jar href="j3dcore.jar"/>
<jar href="j3dutils.jar"/>
<jar href="vecmath.jar"/>
</resources>
<resources os="Windows">
<nativelib href="windows/j3dDLL.jar"/>
</resources>
<resources os="linux" arch="i386">
<nativelib href="linux/i386/j3d.so.jar"/>
</resources>
<resources os="linux" arch="ppc">
<nativelib href="linux/ppc/j3d.so.jar"/>
</resources>
Thus the first four jar file were intended for all platform, with a specific jar for each architecture.
It tried this out with an easy example and it turned out that this code only worked for Windows, but failed under Linux.
The experimenting exposed several problems.
Different Vendors, different arch property
I tried it on a Linux box with an IBM 1.3 JRE. The interesting bit was, that the native lib never got loaded.
The reason being that the IBM JRE doesn't define arch as 'i386', like the SUN JRE does, but uses 'x86'.
No wonder the resource had not been loaded by Web Start.
However this lead to a rather ugly duplication of otherwise identic XML code:
<!-- Linux IBM J2RE 1.3.0 -->
<resources os="Linux" arch="x86">
<nativelib href="jars/j3d/linux/i386/j3d.so.jar"/>
</resources>
<!-- Linux SUN JRE1.3.1 -->
<resources os="Linux" arch="i386">
<nativelib href="jars/j3d/linux/i386/j3d.so.jar"/>
</resources>
Pure java, but a call to a Win32 method
Another problem that showed up, was that at least one of the four to be thought platform neutral jars contained a method call like Win32Foo, a method that exists only on Win32 platform implementations, but not under Linux.
Thus this, plus possible problems with versioning (the Linux Java3D release was slighty behind the Win32 release) lead me to organize the resources into this scheme:
<resources os="Windows">
<jar href="jars/j3d/windows/j3daudio.jar"/>
<jar href="jars/j3d/windows/j3dcore.jar"/>
<jar href="jars/j3d/windows/j3dutils.jar"/>
<jar href="jars/j3d/windows/vecmath.jar"/>
<nativelib href="jars/j3d/windows/j3dDLL.jar"/>
</resources>
<!-- Linux IBM J2RE 1.3.0 -->
<resources os="Linux" arch="x86">
<jar href="jars/j3d/linux/i386/j3daudio.jar"/>
<jar href="jars/j3d/linux/i386/j3dcore.jar"/>
<jar href="jars/j3d/linux/i386/j3dutils.jar"/>
<jar href="jars/j3d/linux/i386/vecmath.jar"/>
<nativelib href="jars/j3d/linux/i386/j3d.so.jar"/>
</resources>
<!-- Linux SUN JRE1.3.1 -->
<resources os="Linux" arch="i386">
<jar href="jars/j3d/linux/i386/j3daudio.jar"/>
<jar href="jars/j3d/linux/i386/j3dcore.jar"/>
<jar href="jars/j3d/linux/i386/j3dutils.jar"/>
<jar href="jars/j3d/linux/i386/vecmath.jar"/>
<nativelib href="jars/j3d/linux/i386/j3d.so.jar"/>
</resources>
<resources os="Solaris" arch="sparc">
<jar href="jars/j3d/solaris/j3daudio.jar"/>
<jar href="jars/j3d/solaris/j3dcore.jar"/>
<jar href="jars/j3d/solaris/j3dutils.jar"/>
<jar href="jars/j3d/solaris/vecmath.jar"/>
<nativelib href="jars/j3d/solaris/j3d.so.jar"/>
</resources>
This time I made sure, that I offer only jars from a specific platform release for each platform.
Regards,
Marc