Embed Java VM in Executables using Java Native Interface (JNI)

Java Native Interface is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform. We can embed java inside any application developed using C/C++ using Java Native Interface.

Here InvokeJVM.C which illustrates some calls in JNI. Please ensure that you are compiling in a multithreaded environment and with JDK117B or JDK12 Header files.

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

#define PATH_SEPARATOR ‘;’ /* platform dependent */
#define USER_CLASSPATH “.” /* directory where Sample.class is present */

typedef jint (*P_JNI_GetDefaultJavaVMInitArgs)(void *args);
typedef jint (*P_JNI_CreateJavaVM)(JavaVM **pvm, JNIEnv ** penv, void *args);

void __cdecl main(int argc, char **argv) {
char classpath[1024]; /* Class Path */
JNIEnv *env = NULL; /* Environment */
JavaVM *jvm = NULL; /* Virtual Machine */
JDK1_1InitArgs vm_args; /* Initializing arguments */
jint res = -1;
jclass cls;
jmethodID mid;
jstring jstr;
jobjectArray args;
HANDLE hLib = NULL;

/* Pointer to required functions */
P_JNI_GetDefaultJavaVMInitArgs pfnGetDefaultJavaVMInitArgs = NULL;
P_JNI_CreateJavaVM pfnCreateJavaVM = NULL;

if(argc < 3){
printf(“Usage : InvokeJVM <javai.dll> <Sample>n”);
exit(-1);
}

/* Load the library */
printf(“Loading Library …. <%s>n”,argv[1]);
hLib = LoadLibrary(argv[1]);

if(hLib == NULL) {
printf(“Unable to Load Library…. exitting….”);
exit(-1);
}

/* Store the function pointer for getting default arguments */
pfnGetDefaultJavaVMInitArgs = (P_JNI_GetDefaultJavaVMInitArgs) GetProcAddress(hLib, “JNI_GetDefaultJavaVMInitArgs”);

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

/* Get the default arguments */
if(pfnGetDefaultJavaVMInitArgs != NULL)
(*pfnGetDefaultJavaVMInitArgs)(&vm_args);

/* Append USER_CLASSPATH to the end of default system class path */
if(vm_args.classpath != NULL)
sprintf(classpath, “%s%c%s”, vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
else
sprintf(classpath, “%s”, USER_CLASSPATH);

vm_args.classpath = classpath;

/* Store the function pointer for creating the VM */
pfnCreateJavaVM = (P_JNI_CreateJavaVM) GetProcAddress(hLib, “JNI_CreateJavaVM”);

/* Create the Java VM */
if(pfnCreateJavaVM != NULL)
res = (*pfnCreateJavaVM)(&jvm,&env,&vm_args);
if (res < 0) {
fprintf(stderr, “Can’t create Java VMn”);
exit(1);
}

/* Find the class that we need to use */
cls = (*env)->FindClass(env, argv[2]);
if (cls == 0) {
fprintf(stderr, “Can’t find %s.classn”,argv[2]);
exit(1);
}

/* get a id to the “main” method */
mid = (*env)->GetStaticMethodID(env, cls, “main”, “([Ljava/lang/String;)V”);
if (mid == 0) {
fprintf(stderr, “Can’t find main function in %s.classn”,argv[2]);
exit(1);
}

/* create a new string to pass as parameter */
jstr = (*env)->NewStringUTF(env, “Hello World!!!”);
if (jstr == 0) {
fprintf(stderr, “Out of memoryn”);
exit(1);
}

/* create a new array */
args = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, “java/lang/String”), jstr);
if (args == 0) {
fprintf(stderr, “Out of memoryn”);
exit(1);
}

/* Ready to rock’n’roll */
(*env)->CallStaticVoidMethod(env, cls, mid, args);

/* All’s well that ends well */
(*jvm)->DestroyJavaVM(jvm);
}

Here is a Sample.java file which has a main() function.

import java.lang.*;
import java.io.*;

/* Sample Class does nothing. It just prints its arguments */
public class Sample
{
static public void main (String argv[])
{
System.out.println(“>>>> Java Version : ” + System.getProperty(“java.version”));
System.out.println(“>>>> Java Vendor : ” + System.getProperty(“java.vendor”));
System.out.println(“>>>> Sample.class started successfully with ” + argv.length + ” argument(s)”);
for(int i=0;i<argv.length;i++)
System.out.println(“>>>> args [“+i+”] : ” + argv[i]);
}
}



Set the PATH, CLASSPATH as follows and then use InvokeJVM

JDK12

SET PATH=D:JDK1.2BIN;D:JDK1.2JREBINCLASSIC;
SET CLASSPATH=.;
INVOKEJVM jvm Sample

JDK117B
SET PATH=D:JDK1.1.7BBIN;
SET CLASSPATH=D:JDK1.1.7BLIBCLASSES.ZIP;.;
INVOKEJVM javai Sample

JDK116
SET PATH=D:JDK1.1.6BIN;
SET CLASSPATH=D:JDK1.1.6LIBCLASSES.ZIP;.;
INVOKEJVM javai Sample

IE – If you have installed the latest Microsoft VM
SET PATH=C:WINNT40SYSTEM32;
SET CLASSPATH=.;
INVOKEJVM msjava Sample

Sample Output for JDK1.1.7B

Loading Library ….
>>>> Java Version : 1.1.7B
>>>> Java Vendor : Sun Microsystems Inc.
>>>> Sample.class started successfully with 1 argument(s)
>>>> args [0] : Hello World!!!

More Information

JDK 1.2 JNI – Java Native Interface Specification

JDK 1.1 JNI – Java Native Interface Specification

Download demo project – 9 KB

Date Last Updated: April 3, 1999

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read