[ This exercise | Solution | Course Notes | Exercises page ]


Help: Exercise 1

Task 1

MathFuncs.java Create the java class that declares the native method. For this exercise, the java class definition is trivial. There are no members or methods defined within the class. There are 2 key points here:
class MathFuncs
{
  public native double calculateAreaOfCircle(double radius);

  static 
  {
    System.loadLibrary("MathFuncsImp");
  }
}

Task 2

Main.java Create the java class that will test the native method.
class Main 
{
  public static void main(String[] args) 
  {
    MathFuncs mf = new MathFuncs();
    double radius = 10.0;
    double area = mf.calculateAreaOfCircle(radius);
    System.out.println("Area of circle with radius " + radius " is " + area);
  }
}

Task 3

Compile MathFuncs.java and Main.java using javac:

  javac MathFuncs.java
  javac Main.java
This, of course, produces MathFuncs.class and Main.class.

Task 4

Using javah, create the C/C++ header file that represents the java MathFuncs class. Be sure to include the -jni switch so that the resulting header file is a JNI-compatible file. Also, don't include the .class extension:
  javah -jni MathFuncs
This creates a file called MathFuncs.h in the same directory as MathFuncs.class:
 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include < jni.h >
/* Header for class MathFuncs */

#ifndef _Included_MathFuncs
#define _Included_MathFuncs
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     MathFuncs
 * Method:    calculateAreaOfCircle
 * Signature: (D)D
 */
JNIEXPORT jdouble JNICALL Java_MathFuncs_calculateAreaOfCircle
  (JNIEnv *, jobject, jdouble);

#ifdef __cplusplus
}
#endif
#endif
It is important that you compile MathFuncs.java in the previous step so that the .class file is available to javah in this step.

Task 5

This is where the real work is done, which is why we have native methods in the first place. There are 4 key points: If you have problems at run-time, they are likely to be caused by this function signature. The safest thing to do to ensure that you won't have any problems is to copy the declaration of the function from the header file generated by javah.
#include "MathFuncs.h"    

JNIEXPORT jdouble JNICALL Java_MathFuncs_calculateAreaOfCircle(JNIEnv *env, jobject obj, jdouble radius) 
{
  const jdouble PI = 3.1415926535;
  jdouble area =  PI * (radius * radius);
  return area;
}

Task 6

This is the step where the actual creation of the shared library happens. It is also the point where we must name the file. It is important that the name matches what the MathFuncs class is expecting when it loads the shared library in its static initialization:

This code is taken from MathFuncs.java:

  static 
  {
      // The name of our shared library must match what
      // the class is loading at initialization time:

    System.loadLibrary("MathFuncsImp");
  }

Here is an example of how to make a shared library under Unix:

# This works on sirius.cs.pdx.edu
# The -o option allows you to name the shared library. Note that
# you must provide the 'lib' prefix and '.so' suffix here.

gcc -G -I/pkgs/jdk1.1.1/include -I/pkgs/jdk1.1.1/include/solaris MathFuncsImp.cpp -o libMathFuncsImp.so

Here is an example of how to make a shared library under Windows NT:

: This works under NT. Replace the include paths to match your environment
: and be sure to include Sun's JDK not Microsoft's!
: Note that you must provide the .dll extension (case insensitive)

cl -Im:\jdk1.1.5\include -Im:\jdk1.1.5\include\win32 -LD MathFuncsImp.cpp -FeMathFuncsImp.dll

Task 7

To execute the program, run Main with the java interpreter:
  java Main
The output should look something like this:
  Area of circle with radius 2 is 25.132741228
If you receive an error message such as either of these:
  java.lang.UnsatisfiedLinkError: no MathFuncsImp in shared library path
  java.lang.UnsatisfiedLinkError: calculateAreaOfRectangle
refer to the
common mistakes in the detailed example.

Copyright © 1998 Sergio Antoy. All Rights Reserved
February 99, version 020199