|
NAG Technical Report TR 3/2000Calling the NAG C Library from Java
Motivation
For someone needing to perform numerical computations,
one approach is to create Java classes implementing the
required functionality; a group who have made progress in
this direction, partly by writing new code and partly by converting
pre-existing code from other languages into Java, is the
Numerics Working Group of the Java Grande Forum.
The JavaNumerics web page
[4]
gives much useful information, including discussion
of the difficulties of using Java for numerical computation
due to constraints imposed by Java as it currently stands.
In this report, we use the alternative
approach of calling the NAG C Library directly from Java,
thus evading the job of writing or rewriting code,
and everything that that entails in the way of testing.
Of course, since we propose to call the NAG Library, our application
will no longer be portable in the sense that it would have been
had it been exclusively written in Java, because now it will rely
on the presence of a machine-dependent implementation of the NAG
Library at run time. However, it will still be portable in
the sense that the NAG C Library is available on almost all
commercially significant machines.
Apart from avoiding the need to first write Java versions of
numerical routines, using the NAG C Library has another advantage.
Java has been designed to be portable; a compiled program will run on any
machine which has an implementation of the Java Virtual Machine (VM).
To accomplish this, the Java compiler does not compile to
machine-dependent assembler, as do traditional languages such
as C or C++, but to a machine-independent byte code. This
byte code then gets interpreted at run time by the VM.
Although the Java interpreter is efficient, it is clear that it
would be hard for any interpreted program to run as fast
as a program compiled to assembler code. For many applications
this does not matter; but for applications that perform
cpu-intensive operations on large amounts of data, it may
be significant. By moving those operations out of Java and
into the NAG Library, we may therefore hope to cut execution
time.
In order to access the NAG C Library from a Java program, we will
make use of the Java Native Interface.
At compile time, the JNI defines the way that Java data types
correspond to C data types – C programs get this information
from JNI header files that come with the JDK. A tool, javah,
that comes with the JDK, aids in creating application-specific header
files which aim to eliminate mistakes in communication
between Java and C routines.
At run time, the JNI allows the passing of Java objects
to the C code, and allows the C code access to
Java properties and methods. Thus, for example,
the C code can set properties of Java classes, and it is possible
to call a Java method from C.
During preparation of this report, we used JDK version 1.2 (now known
as Java 2 SDK, SE v1.2) on two machines
Working on UNIX platforms other than Sun/Solaris should be
similar to Solaris; the main differences are likely to be in the
location of Java include files, and the
method of creating a shared object (dynamic library).
A good introduction to the Java Native Interface
can be found at the Sun Microsystems Java Tutorial web site
[5].
The interface library is required because when a native method (i.e.
function or subroutine) is
called from Java, extra arguments are prepended to the argument list
of the native routine being called. These extra arguments give the
native code access to Java methods and properties, but of course
the NAG C Library was not designed to handle these arguments.
Furthermore, the types of the arguments passed from Java
do not always correspond exactly to standard C types, and so the
NAG C Library cannot use them directly.
The interface library must handle these issues, make its
own calls to the NAG Library, and then send the results back to Java.
Implementation of a call from Java to the NAG C Library is a
three-stage process
When the interface library has been built, the Java code
that uses it is still machine-independent even though the
interface library is not. Thus, we need to
build the interface library on all platforms that we are
interested in, but we do not have to edit or rebuild the Java code
that uses it.
With a little more effort it should also be possible to interface
to other NAG Libraries, such as the NAG Fortran 77 Library. In this case,
it may be possible to create the interface library for some
routines in Fortran rather than C. However, there is little doubt
that it would be easier to continue to write the interface in C,
and then make calls to the NAG Fortran Library from C. The issue of
how C types correspond to Fortran types will arise, and
for routines that use multi-dimensional arrays, the storage conventions
adopted by the different languages will need to be taken into account;
C and Java both use row-major
order for 2D arrays, whereas Fortran uses column-major
order. This means that at some point, in either the Java or
C code, arrays may need to be transposed.
If you are interested in calling NAG Fortran routines
from Java, NAG supplies header files [6]
that can help to make it easier to call NAG Fortran 77 Library
routines from an interface library written in C.
|