next up previous
Next: Experiments Up: A Note on Native Java Previous: Introduction

Native BLAS

 In Java, if the keyword native appears as part of a method definition (without an implementation), then this implies that the method is implemented in another language. A set of primitives from BLAS, for instance, can be defined using the following class that provides a shared library loader that will load the actual implementation when required as well as definitions of all primitives in the set:

SPMquotclass Blas "
SPMquot "
SPMquot // Shared Library Loader"
SPMquot "
SPMquot static "
System.loadLibrary("blas");
SPMquot "
SPMquot "
SPMquot // Level 1 BLAS"
SPMquot "
SPMquot native static double ddot(int n, double[] x, int xoff, int incx,"
SPMquot double[] y, int yoff, int incy);"
SPMquot native static void daxpy(int n, double alpha, double[] x, int xoff, int incx,"
SPMquot double[] y, int yoff, int incy);"
SPMquot "
SPMquot ..."
SPMquot"


  
Figure 1: Integration of Native Methods
\begin{figure}
\begin{center}
\centerline{
\resizebox {12cm}{!}{\includegraphics{nat.ps}}
}\end{center}\end{figure}

Here, method definitions of DDOT ($d \leftarrow \vec{x}\,^T \vec{y}$ in double precision) and DAXPY ($\vec{y} \leftarrow \alpha \vec{x} + \vec{y}$in double precision) are shown.[*] Alternatively, as stated earlier, Java implementations of the primitives could be given in first instance.

In figure 1, the integration of native methods in Java is illustrated. Using JDK1.0.2, first the source file Blas.java is compiled into Blas.class using the Java compiler javac. Subsequently, the tool javah is used to generate a stubs file Blas.c and a header file Blas.h. The latter file contains C prototypes for all native methods in the class. The actual implementation of these methods is given in a file BlasImp.c. Method ddot(), for example, can be implemented in a straightforward manner in C as follows, where the macro unhand() is used to dereference an object handle:

 
Figure 1: Integration of Native Methods
#include <StubPreamble.h>
#include "Blas.h"
SPMquot "
SPMquotdouble Blas_ddot(struct HBlas *this, long n,"
SPMquot HArrayOfDouble *x_, long xoff, long incx,"
SPMquot HArrayOfDouble *y_, long yoff, long incy) "
SPMquot double *x = unhand(x_)->body;"
SPMquot double *y = unhand(y_)->body;"
SPMquot double d = 0;"
SPMquot "
SPMquot if (n > 0) "
SPMquot if ((incx == 1)
SPMquot int i;"
SPMquot for (i=0;i < n; i++)"
SPMquot d += x[xoff+i]*y[yoff+i];"
SPMquot "
SPMquot else /* Non-Unit strides */"
SPMquot ..."
SPMquot "
SPMquot "
SPMquot return d;"
SPMquot"

Eventually, the files Blas.c and BlasImp.c are compiled into a shared library. The way in which this is done and the naming convention of shared libraries depends on the target architecture (under Solaris, for instance, the shared library is created as:

SPMquotcc -G -O -I JAVAHOME/include -IJAVA_HOME/include/solaris Blas.c BlasImp.c -o libblas.so"

As illustrated in the second picture in figure 1, integrating native methods in JDK1.1 is slightly different. Only a header file Blas.h which contains the appropriate prototypes is generated using javah -jni. The actual implementation of methods is, again, given in a file BlasImp.c Method ddot(), for example, can be implemented in C as follows, where functions GetDoubleArrayElements() and ReleaseDoubleArrayElements() are used to obtain and release a double array that cannot be moved by the garbage collector. Eventually, the whole file is compiled into a shared library:

#include "Blas.h"
SPMquotJNIEXPORT jdouble JNICALL Java_Blas_ddot"
SPMquot (JNIEnv *env, jclass class, jint n, jdoubleArray x_, jint xoff, jint incx,"
SPMquot jdoubleArray y_, jint yoff, jint incy) "
SPMquot jdouble *x = (*env)->GetDoubleArrayElements(env, x_, 0);"
SPMquot jdouble *y = (*env)->GetDoubleArrayElements(env, y_, 0);"
SPMquot jdouble d = 0;"
SPMquot "
SPMquot if (n > 0) "
SPMquot if ((incx == 1)
SPMquot int i;"
SPMquot for (i=0;i < n; i++)"
SPMquot d += x[xoff+i]*y[yoff+i];"
SPMquot "
SPMquot else /* Non-Unit strides */"
SPMquot ..."
SPMquot "
SPMquot "
SPMquot (*env)->ReleaseDoubleArrayElements(env, x_, x, 0);"
SPMquot (*env)->ReleaseDoubleArrayElements(env, y_, y, 0);"
SPMquot return d;"
SPMquot"

If native methods are used, care must be taken with respect to the precision of the computed result, because Java data types are mapped to the nearest matching data types on the native language side . More details on integrating native methods in Java can be found on the Web [16].


next up previous
Next: Experiments Up: A Note on Native Java Previous: Introduction
ajcbik@extreme.indiana.edu