• An interface pointer,jvm, to the newly created Java virtual machine.
• The JNIEnv interface pointer env for the current thread. Recall that native code accesses JNI functions through theenv interface pointer.
When theJNI_CreateJavaVMfunction returns successfully, the current native thread has bootstrapped itself into the Java virtual machine. At this point it is run- ning just like a native method. Thus it can, among other things, issue JNI calls to invoke theProg.main method.
Eventually the program calls theDestroyJavaVMfunction to unload the Java virtual machine. (Unfortunately, you cannot unload the Java virtual machine implementation in JDK release 1.1 or Java 2 SDK release 1.2. DestroyJavaVM
always returns an error code in these releases.) Running the above program produces:
Hello World from C!
7.2 Linking Native Applications with the Java Virtual Machine
The invocation interface requires you to link programs such as invoke.cwith a Java virtual machine implementation. How you link with the Java virtual machine depends on whether the native application is intended to be deployed with only a particular virtual machine implementation or it is designed to work with a variety of virtual machine implementations from different vendors.
7.2.1 Linking with a Known Java Virtual Machine
You may decide that your native application will be deployed only with a particu- lar virtual machine implementation. In this case you can link the native applica- tion with the native library that implements the virtual machine. For example, with the JDK 1.1 release for Solaris, you can use the following command to com- pile and linkinvoke.c:
cc -I<jni.h dir> -L<libjava.so dir> -lthread -ljava invoke.c
The -lthread option indicates that we use the Java virtual machine imple- mentation with native thread support (§8.1.5). The -ljava option specifies that
libjava.sois the Solaris shared library that implements the Java virtual machine.
THE INVOCATION INTERFACE Linking with Unknown Java Virtual Machines 7.2.2 On Win32 with the Microsoft Visual C++ compiler, the command line to
compile and link the same program with JDK 1.1 release is:
cl -I<jni.h dir> -MD invoke.c -link <javai.lib dir>\javai.lib
Of course, you need to supply the correct include and library directories that correspond to the JDK installation on your machine. The-MDoption ensures that your native application is linked with the Win32 multithreaded C library, the same C library used by the Java virtual machine implementation in JDK 1.1 and Java 2 SDK 1.2 releases. The cl command consults the javai.lib file, shipped with JDK release 1.1 on Win32, for linkage information about invocation interface functions such as JNI_CreateJavaVM implemented in the virtual machine. The actual JDK 1.1 virtual machine implementation used at run time is contained in a separate dynamic link library file calledjavai.dll. In contrast, the same Solaris shared library (.so file) is used both at link time and at run time.
With Java 2 SDK release 1.2, virtual machine library names have changed to
libjvm.soon Solaris and tojvm.libandjvm.dllon Win32. In general, differ- ent vendors may name their virtual machine implementations differently.
Once compilation and linking are complete you can run the resulting execut- able from the command line. You may get an error that the system cannot find either a shared library or a dynamic link library. On Solaris, if the error message indicates that the system cannot find the shared library libjava.so (or lib- jvm.soin Java 2 SDK release 1.2), then you need to add the directory containing the virtual machine library to yourLD_LIBRARY_PATHvariable. On a Win32 sys- tem, the error message may indicate that it cannot find the dynamic link library
javai.dll (or jvm.dll in Java 2 SDK release 1.2). If this is the case, add the directory containing the DLL to yourPATH environment variable.
7.2.2 Linking with Unknown Java Virtual Machines
You cannot link the native application with one specific library that implements a virtual machine if the application is intended to work with virtual machine imple- mentations from different vendors. Because the JNI does not specify the name of the native library that implements a Java virtual machine, you should be prepared to work with Java virtual machine implementations that are shipped under differ- ent names. For example, on Win32 the virtual machine is shipped asjavai.dllin JDK release 1.1 and asjvm.dll in Java 2 SDK release 1.2.
7.2.2 Linking with Unknown Java Virtual Machines THE INVOCATION INTERFACE
The solution is to use run-time dynamic linking to load the particular virtual machine library needed by the application. The name of the virtual machine library can then be easily configured in an application-specific way. For example, the following Win32 code finds the function entry point for JNI_CreateJavaVM
given the path of a virtual machine library:
/* Win32 version */
void *JNU_FindCreateJavaVM(char *vmlibpath) {
HINSTANCE hVM = LoadLibrary(vmlibpath);
if (hVM == NULL) { return NULL;
}
return GetProcAddress(hVM, "JNI_CreateJavaVM");
}
LoadLibraryandGetProcAddressare the API functions for dynamic linking on Win32. AlthoughLoadLibrarycan accept either the name (such as "jvm") or the path (such as "C:\\jdk1.2\\jre\\bin\\classic\\jvm.dll") of the native library that implements the Java virtual machine, it is preferable that you pass the absolute path of the native library toJNU_FindCreateJavaVM. Relying onLoadL- ibraryto search forjvm.dllmakes your application susceptible to configuration changes, such as additions to thePATH environment variable.
The Solaris version is similar:
/* Solaris version */
void *JNU_FindCreateJavaVM(char *vmlibpath) {
void *libVM = dlopen(vmlibpath, RTLD_LAZY);
if (libVM == NULL) { return NULL;
}
return dlsym(libVM, "JNI_CreateJavaVM");
}
Thedlopenanddlsymfunctions support dynamically linking shared libraries on Solaris.
THE INVOCATION INTERFACE Attaching Native Threads 7.3