Using the Invocation API


Up to now, we have considered programs in the Java programming language that made a few C calls, presumably because C was faster or allowed access to functionality that was inaccessible from the Java platform. Suppose you are in the opposite situation. You have a C or C++ program and would like to make a few calls to Java code, perhaps because the Java code is easier to program. Of course, you know how to call the Java methods. But you still need to add the Java virtual machine to your program so that the Java code can be interpreted. The so-called invocation API enables you to embed the Java virtual machine into a C or C++ program. Here is the minimal code that you need to initialize a virtual machine.

 JavaVMOption options[1]; JavaVMInitArgs vm_args; JavaVM *jvm; JNIEnv *env; options[0].optionString = "-Djava.class.path=."; memset(&vm_args, 0, sizeof(vm_args)); vm_args.version = JNI_VERSION_1_2; vm_args.nOptions = 1; vm_args.options = options; JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args); 

The call to JNI_CreateJavaVM creates the virtual machine and fills in a pointer, jvm, to the virtual machine and a pointer, env, to the execution environment.

You can supply any number of options to the virtual machine. Simply increase the size of the options array and the value of vm_args.nOptions. For example,

 options[i].optionString = "-Djava.compiler=NONE"; 

deactivates the just-in-time compiler.

TIP

When you run into trouble and your program crashes, refuses to initialize the JVM, or can't load your classes, then turn on the JNI debugging mode. Set an option to

 options[i].optionString = "-verbose:jni"; 

You will see a flurry of messages that indicate the progress in initializing the JVM. If you don't see your classes loaded, check both your path and your class path settings.


Once you have set up the virtual machine, you can call Java methods in the way described in the preceding sections: Simply use the env pointer in the usual way. You need the jvm pointer only to call other functions in the invocation API. Currently, there are only four such functions. The most important one is the function to terminate the virtual machine:

 (*jvm)->DestroyJavaVM(jvm); 

The C program in Example 11-20 sets up a virtual machine and then calls the main method of the Welcome class, which was discussed in Volume 1, Chapter 2. (Make sure to compile the Welcome.java file before starting the invocation test program.)

Example 11-20. InvocationTest.c

[View full width]

  1. #include <jni.h>  2. #include <stdlib.h>  3.  4. int main()  5. {  6.    JavaVMOption options[2];  7.    JavaVMInitArgs vm_args;  8.    JavaVM *jvm;  9.    JNIEnv *env; 10.    long status; 11. 12.    jclass class_Welcome; 13.    jclass class_String; 14.    jobjectArray args; 15.    jmethodID id_main; 16. 17.    options[0].optionString = "-Djava.class.path=."; 18. 19.    memset(&vm_args, 0, sizeof(vm_args)); 20.    vm_args.version = JNI_VERSION_1_2; 21.    vm_args.nOptions = 1; 22.    vm_args.options = options; 23. 24.    status = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args); 25.    if (status == JNI_ERR) 26.    { 27.       printf("Error creating VM\n"); 28.       return 1; 29.    } 30. 31.    class_Welcome = (*env)->FindClass(env, "Welcome"); 32.    id_main = (*env)->GetStaticMethodID(env, class_Welcome, "main", "([Ljava/lang /String;)V"); 33. 34.    class_String = (*env)->FindClass(env, "java/lang/String"); 35.    args = (*env)->NewObjectArray(env, 0, class_String, NULL); 36.    (*env)->CallStaticVoidMethod(env, class_Welcome, id_main, args); 37. 38.    (*jvm)->DestroyJavaVM(jvm); 39. 40.    return 0; 41. } 

To compile this program under Linux, use


gcc -I jdk/include -I jdk/include/linux -o InvocationTest
   -L jdk/jre/lib/i386/client -ljvm InvocationTest.c

Under Solaris, use


cc -I jdk/include -I jdk/include/solaris -o InvocationTest
    -L jdk/jre/lib/sparc -ljvm InvocationTest.c

When compiling in Windows with the Microsoft C compiler, use the command line


cl -I jdk\include -I jdk\include\win32 InvocationTest.c jdk\lib\jvm.lib

With Cygwin, you have to work a little harder. First make a file, jvm.def, that contains the statement

 EXPORTS    JNI_CreateJavaVM@12 

Run the command


dlltool -k --input-def jvm.def --dll jdk\\jre\\bin\\client\\jvm.dll --output-lib jvm.a

CAUTION

If you issue this command from the bash shell, supply four backslashes \\\\ for each file separator.


Then compile with


gcc -I jdk\include -I jdk\include\win32 -D__int64="long long" -o InvocationTest
   InvocationTest.c jvm.a

Before you run the program under Linux/UNIX, make sure that the LD_LIBRARY_PATH contains the directories for the shared libraries. For example, if you use the bash shell on Linux, issue the following command:


export LD_LIBRARY_PATH=jdk/jre/lib/i386/client:$LD_LIBRARY_PATH

On Windows, make sure the directory


jdk\jre\bin\client

is on the PATH.

CAUTION

The exact locations of the various library files varies somewhat from one release of the JDK to the next. You may need to search for files called libjvm.so, jvm.dll, or (with older JDK versions) libjava.so, in the jdk/bin, jdk/lib, and jdk/jre/lib directories and adjust the instructions accordingly.


TIP

If you develop an application that invokes the virtual machine by using a Windows launcher, then you may not trust your users to set the library path. You can help your users and load the shared library or DLL manually. The javac and java programs do just that. For sample code, see the file launcher/java_md.c in the src.jar file that is a part of the JDK.



 Invocation API Functions 

  • jint JNI_CreateJavaVM(JavaVM** p_jvm, void** p_env, JavaVMInitArgs* vm_args)

    initializes the Java virtual machine. The function returns 0 if successful, JNI_ERR on failure.

    Parameters:

    p_jvm

    Filled with a pointer to the invocation API function table

     

    p_env

    Filled with a pointer to the JNI function table

     

    vm_args

    The virtual machine arguments


  • jint DestroyJavaVM(JavaVM* jvm)

    destroys the virtual machine. Returns 0 on success, a negative number on failure. This function must be called through a virtual machine pointer, i.e., (*jvm)->DestroyJavaVM(jvm).

    Parameters:

    jvm

    The virtual machine pointer




    Core JavaT 2 Volume II - Advanced Features
    Building an On Demand Computing Environment with IBM: How to Optimize Your Current Infrastructure for Today and Tomorrow (MaxFacts Guidebook series)
    ISBN: 193164411X
    EAN: 2147483647
    Year: 2003
    Pages: 156
    Authors: Jim Hoskins

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net