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

Embed Java code into your native apps

Integrate a Java user interface with legacy code on Unix

  • Print
  • Feedback
Like many developers, you want to incorporate new Java technologies into your projects. But currently your code is written in C or in another legacy language, and rewriting your entire application in Java is not a realistic option. In this article you will learn how to embed Java code into your native application and how to integrate GUIs of multiple worlds: Motif, the XToolKit, X Window and OpenGL for Unix, and Swing for Java.

After reading this article you will be able to:

  • Start a JVM from a legacy application
  • Create Java objects from a legacy application
  • Integrate a Swing GUI with the Motif window manager
  • Call back legacy code from Java using a thread-safe architecture


Where to start?

Consider a simple C program with a Motif user interface. By browsing through its menus, currently the user can create OpenGL windows that contain some simple 3D rendering. You have been asked to add a new menu to this application; you want to implement it using the Swing package from the JDK. The Java Native Interface (JNI) API from the Java Runtime Environment provides you with the tools you need to start a JVM from a C program and accomplish the task at hand. Using that JVM, JNI also allows you to create Java objects and call the objects' methods. Assuming that you have written the code needed for a Java class that implements the required menu (see SwingMenu.java for the full Java code, available for download from Resources), you now have to access the JNI from the C code to start the JVM and load your class. Listing 1 illustrates those last two tasks:

Listing 1: Start the JVM and load a class

/** File main.c **/
#include <stdlib.h>
#include <jni.h>
int main (int argc, char *argv[])
{
JNIEnv          *env;
JavaVM          *jvm;
JavaVMInitArgs  vm_args;
JavaVMOption    options[3];
int             nbOptions;
jint            res;
jclass          myJavaClass;
jobject         javaGUI;
jmethodID       constructorID;
char            *classPath, *libraryPath;
/** Code to be added here **/ 
/** Start the Java Virtual Machine **/
classPath = malloc(29);
strcpy(classPath, "-Djava.class.path=/myClassDir");   /* Path of the
SwingManu.class file */
libraryPath = malloc(29);
strcpy(libraryPath, "-Djava.library.path=/myLibDir");     /* Path of
the libNativeMethods.so library */
nbOptions=0;
options[0].optionString = classPath;   nbOptions++;
options[1].optionString = libraryPath; nbOptions++;
vm_args.version  = JNI_VERSION_1_2;                   /* Specifies the JNI
version used */
vm_args.options  = options;
vm_args.nOptions = nbOptions;
vm_args.ignoreUnrecognized = JNI_TRUE;                 /* JNI won't
complain about unrecognized options */
res = JNI_CreateJavaVM(&jvm,(void **)&env,&vm_args);
free(classPath);
free(libraryPath);
/*
 * Create an instance of the Class SwingMenu.
 * Before calling NewObject we must get the constructor
 * of the Java class. This constructor must de passed
 * as an argument to NewObject.
 */
myJavaClass   = (*env)->FindClass(env, "SwingMenu");
constructorID = (*env)->GetMethodID(env,myJavaClass,"<init>", 
"()V");
javaGUI       = (*env)->NewObject(env,myJavaClass,constructorID);
}


Job done! You are now able to start your application. With a few Java method invocations through JNI you can see your Swing menu on the screen. Below is the picture of your application at startup.

  • Print
  • Feedback

Resources