Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Ready Java example: Embed JVM into native code.

JavaFAQ Home » Java Code Examples Go to all tips in Java Code Examples


Bookmark and Share

Today we added a collection of sample JNI (Java Native Interace) programs. The ideas are mostly taken from the Sun Java tutorial.

EmbeddingJVM : This code sample illustrates how to embed and call the JVM from a native program.

Code:



/* JNIEmbed.c */

/**
 * Invoking the Java Virtual Machine
 * ---------------------------------
 *
 * The JDK ships the Java Virtual Machine as a shared library
 * (or dynamic link library on Win32). You can embed the Java
 * Virtual Machine into your native application by linking
 * the native application with the shared library.
 *
 * The JNI supports an Invocation API that allows you to load,
 * initialize, and invoke the Java Virtual Machine. Indeed,
 * the normal way of starting the Java interpreter, java, is
 * no more than a simple C program that parses the command line
 * arguments and invokes the Java Virtual Machine through the
 * Invocation API.
 *
 * This program is an implementation of the lessons in the Sun
 * Java Tutorial. Though it will require only minor changes to
 * run this on multiple platforms, currently this has been
 * developed and tested on Windows 2000.
 *
 * Author: Tanmay K. M.
 * http://tanmaykm.tripod.com/
 */

#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <jni.h>

/*
Include jni.h for JNI specific methods. This header file can
be found in the JDK include directory. Include the path to
the JNI include directories in your project make file.
For example:
If you have JDK 1.3.1 installed in C:\ directory, include
the following two directories:

C:\jdk1.3.1\include
C:\jdk1.3.1\include\win32

In addition you must link your executable to the jvm.lib
library and add the path to the jvm.dll to your PATH or
LD_LIBRARY_PATH environment variable to enable the exe
to load the JVM.

Compile a Java class with main (an example java file is
provided:

public class JNIEmbedTest
{
   public static void main(String [] args)
   {
      System.out.println("Hello from JNIEmbedTest");
      System.out.println("String from C: " + args[0]);
   }
}

Place both the executable and the class file in the same
directory and execute the executable with the Java class
file name as the argument.
*/

/* The path where the class file being executed can be found */
#define USER_CLASSPATH "."
#define USER_LIBPATH "."

/*
 The following structure is used to pass data from the
 main thread to worker threads. The usage of this will
 become clear later in the program.
*/
typedef struct threadData
{
   JNIEnv         *env;
   JavaVM         *jvm;
   char         *sClassName;
   int            iThreadIndex;
} tstThreadData;

/**
 * CallMain
 *
 * Calls the main method of a class file.
 * Passes the string "Hello World frm C!" to the Java
 * class as the argument to the main method.
 */
int CallMain(JNIEnv *env, JavaVM *jvm, const char *sClassName)
{
   jclass         cls;
   jmethodID      mid;
   jstring         jstr;
   jobjectArray   args;

   /* locate and load the class file */
    if ((cls = (*env)->FindClass(env, sClassName)) == 0)
   {
        fprintf(stderr, "Can't find class %s\n", sClassName);
        return -1;
    }
 
   /* locate the main method */
    if ((mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V")) == 0)
   {
        fprintf(stderr, "Can't find main method in class %s\n", sClassName);
        return -1;
    }

   /* create a new java string to be passes to the class */
    if ((jstr = (*env)->NewStringUTF(env, "Hello World from C!")) == 0)
   {
        fprintf(stderr, "Out of memory\n");
        return -1;
    }

   /* create a new string array with a single element containing the
   string created above */
    args = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), jstr);
    if (args == 0)
   {
        fprintf(stderr, "Out of memory\n");
        return -1;
    }

   /* call the main method with the required arguments */
    (*env)->CallStaticVoidMethod(env, cls, mid, args);

   return 0;
}

/**
 * CallMainInThread
 *
 * Calls the main method of the class file inside a worker
 * thread created in C. This involves attaching the native
 * thread to the JVM and involing the main method in the thread.
 */
int CallMainInThread(JNIEnv *env, JavaVM *jvm, const char *sClassName, int threadNum)
{
   jint res;

   /* attach the current native thread created in C to the JVM */
   /* pass NULL as the third argument */
   res = (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL);
   if (res < 0)
   {
      fprintf(stderr, "Thread %d: attach failed\n", threadNum);
      return -1;
   }

   printf("Thread %d running\n", threadNum);
   /* call the main method. the method will now be called in the
   context of the C thread, which has now been attached to the JVM */
   CallMain(env, jvm, sClassName);

   /* print out any exceptions that might have occured in Java */
   /* It is extremely important to check, handle, and clear the pending
   exception before calling subsequent JNI functions. Calling arbitrary
   JNI functions with a pending exception may lead to unexpected results.
   You can safely call only a small number of JNI functions when there
   is a pending exception. These functions are ExceptionOccurred,
   ExceptionDescribe, and ExceptionClear.
   */
   if ((*env)->ExceptionOccurred(env))
   {
      (*env)->ExceptionDescribe(env);
      (*env)->ExceptionClear(env);
   }

   /* detach the current thread from the JVM. */
   (*jvm)->DetachCurrentThread(jvm);

   return 0;
}

/**
 * TestThread
 *
 * This method is the entry point for the C thread. The argument it
 * receives is an instance of the structure of type tstThreadData.
 * It extracts the relevant stuff from the structure and calls the
 * method CallMainInThread to actually attach the thread to the JVM
 * and call the Java class.
 */
void TestThread(void *args)
{
   tstThreadData *pThreadData = (tstThreadData *)args;

   CallMainInThread(pThreadData->env, pThreadData->jvm, pThreadData->sClassName, pThreadData->iThreadIndex);

   _endthread();
}

/**
 * The main method.
 * Creates the JVM. Calls the Java class in both threaded and
 * non-threaded manner
 */
int main(int argc, char **argv)
{
   JNIEnv         *env;
   JavaVM         *jvm;
   JavaVMInitArgs    vm_args;
   JavaVMOption   options[4];
   jint         res;
   int            iThreadIndex;
   tstThreadData   *pThreadData;

    /* IMPORTANT: specify vm_args version # if you use JDK1.1.2 and beyond */
    vm_args.version = JNI_VERSION_1_2;
   vm_args.nOptions = 0;

   options[0].optionString = "-Djava.compiler=NONE"; /* disable JIT */
   options[1].optionString = "-Djava.class.path=" USER_CLASSPATH; /* user classes */
   options[2].optionString = "-Djava.library.path=" USER_LIBPATH; /* set native library path */
   options[3].optionString = "-verbose:jni"; /* print JNI-related messages */

   if(1 == argc)
   {
        fprintf(stderr, "Usage: %s <main class name>\n", argv[0]);
        exit(1);
   }

   printf("Running class %s.\n", argv[0]);
   printf("After the program is finished, press ENTER to terminate the JVM.\n");

    /* Create the Java VM */
    if ((res = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args)) < 0)
   {
        fprintf(stderr, "Can't create Java VM\n");
        exit(1);
    }

   /* call the main method of the Java class from the main thread */
   CallMain(env, jvm, argv[1]);

   /* Create 5 threads and call the Java class from the threads */
   pThreadData = malloc(5 * sizeof(tstThreadData));

    for (iThreadIndex=0; iThreadIndex<5; iThreadIndex++)
   {
      tstThreadData   *pThisThreadData = pThreadData + iThreadIndex;

      pThisThreadData->env = env;
      pThisThreadData->jvm = jvm;
      pThisThreadData->sClassName = argv[1];
      pThisThreadData->iThreadIndex = iThreadIndex;
        /* We pass the thread number as the argument to every thread */
        _beginthread(TestThread, 0, (void *)pThisThreadData);
   }

   getchar();

   free(pThreadData);

   /* destroy the JVM */
    (*jvm)->DestroyJavaVM(jvm);

   return 0;
}




Code:



/* JNIEmbedTest.java
 This is a sample program for use with JNIEmbed.c.
 After compiling JNIEmbed, you can invoke JNIEmbed
 with this class as the parameter.
*/
public class JNIEmbedTest
{
   public static void main(String [] args)
   {
      System.out.println("Hello from JNIEmbedTest");
      System.out.println("String from C: " + args[0]);
   }
}


 Printer Friendly Page  Printer Friendly Page
 Send to a Friend  Send to a Friend

.. Bookmark and Share

Search here again if you need more info!
Custom Search



Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy