Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Use native methods to expand the Java environment

Learn how to interact with libraries and applications written in other languages

  • Print
  • Feedback

Page 3 of 7

  • Start the Java application.

  • Pass parameters to the Java application and retrieve parameters from the Java application.

  • Attach to the VM.

    This step is optional and used only if you wish to attach to the VM from another thread. In this case, you will have multiple threads running in your C application, each of which needs to use the Java application (for example, a Java application that provides some service used by many competing processes).

  • Unload the VM.

    The calling thread must unload the VM.



  • The JNI specification details a concept called embedding. The idea with embedding is to create a Java VM that exists in your address space bound to a single thread of the target OS. (On some systems, specifically those that support thousands of threads, embedding may not be the optimum solution.) "But what about multithreading?," you ask. Embedding does not do away with multithreading; what it does do, however, is allow the Java threads from the VM to be visible to only the calling thread -- unless additional methods are invoked. (This is an advanced concept and will not be discussed further in this article. For additional information, see The Invocation API in Chapter 5 of the JNI specification 1.1.)

    We're going to be working through a fully debugged example, which I encourage you to modify for your own purposes. This example doesn't do very much other than demonstrate how to:

    1. Start the VM.

    2. Reference methods in the application associated with the VM.

    3. Pass objects back and forth between the two environments. In some cases, the objects may not really be objects -- in C, for instance, you might pass in a structure.


    The example consists of two parts: InstantiatedFromC.java, a Java class that implements some operation we wish to use from C; and tcl2JavaVM.c, the C program in which we wish to use the Java class. The reason for the name tcl2JavaVM.c is for a future plan to allow TCL/TK to use existing Java classes.

    We'll start by specifying an include file that defines the JNI typedefs and defines for the language being used. (You can find this include file in the $JAVA_HOME/lib/include directory, which is included in the JDK developer distribution.) This include file has enough intelligence to determine if you are using C or C++ and generates the appropriate code.

     
    #include <jni.h>
    


    The following variables provide us with a handle to the VM, the default starting arguments, and a debugging aid. I'll leave it to you to determine how you would specify options -- other than the default options -- to the VM using the vm_args variable.

    JavaVM           *jvm;             /* Pointer to a Java VM */
    JNIEnv           *env;             /* Pointer to native method interface */
    JDK1_1InitArgs   vm_args;          /* JDK 1.1 VM initialization requirements */
    int              verbose = 1;      /* Debugging flag */ 
    


    Not much to explain here; the variables do pretty much what the comments indicate:

    • *jvm points to the Java VM that we'll create.

    • *env points to the native method interface of the VM.

    • vm_args contains args and other options, such as the CLASSPATH.

    • verbose = 1 is a debugging flag that allows debugging information to be turned on and off.


    Now let's take a look at the main entry point of the C program. When the computer begins executing tcl2JavaVM, a Java VM will be started with default arguments.

    • Print
    • Feedback

    Resources