Embed Java VM in Executables using Java Native Interface (JNI)
Posted
by Davanum Srinivas
on April 3rd, 1999
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 VM\n");
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.class\n",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.class\n",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 memory\n");
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 memory\n");
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.2\BIN;D:\JDK1.2\JRE\BIN\CLASSIC; SET CLASSPATH=.; INVOKEJVM jvm SampleJDK117B
SET PATH=D:\JDK1.1.7B\BIN; SET CLASSPATH=D:\JDK1.1.7B\LIB\CLASSES.ZIP;.; INVOKEJVM javai SampleJDK116
SET PATH=D:\JDK1.1.6\BIN; SET CLASSPATH=D:\JDK1.1.6\LIB\CLASSES.ZIP;.; INVOKEJVM javai SampleIE - If you have installed the latest Microsoft VM
SET PATH=C:\WINNT40\SYSTEM32; SET CLASSPATH=.; INVOKEJVM msjava SampleSample 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 SpecificationJDK 1.1 JNI - Java Native Interface Specification
Date Last Updated: April 3, 1999

Comments
Unhandled win32 exception
Posted by Legacy on 02/04/2004 12:00amOriginally posted by: Hannne
When I run the the prog with jvm I get unhandled win32 exception, and when I try with msjava it works, the problem is that it's spesified that I'm to use Sun's java vm.
I use java2sdk 1.4.02 and visual studio 6 on win xp..
ReplyI received "Can't create Java VM". Where is the problem?
Posted by Legacy on 09/12/2000 12:00amOriginally posted by: Alexi Jordanov
Hi, I try to use your example but I'm receiving Can't create Java VM error. This is the way for executing :
1) SET PATH=C:\JDK\1.2.2\BIN;C:\JDK\1.2.2\JRE\BIN\CLASSIC;%PATH%
2) SET CLASSPATH=.;C:\JDK\1.2.2\lib\tools.jar;C:\JDK\1.2.2\jre\lib\rt.jar;
3) SET JVMDLL=jvm
4) INVOKEJVM %JVMDLL% Sample
Where is then the problem?
Best regards, Alex
PS :
C:\>java -version
java version "1.2.2"
Classic VM (build JDK-1.2.2-W, native threads, symcjit)
ReplyTLS not working
Posted by Legacy on 06/25/1999 12:00amOriginally posted by: Ulrich Waibel
Hi,
if you are calling a function which resides in an other .dll or .lib and this function uses Thread loacal storage, it doesn't work with JDK 1.1.x and 1.2
On sun's developer connection you will find a very short message about this.
ReplyRegards Uli
missing jni.h file
Posted by Legacy on 05/18/1999 12:00amOriginally posted by: bob
I compiled it with vc++ 5.0. jni.h not included.
ReplyI just like to know how to get it.
thanks.