![]() ![]() ![]() |
Start of Tutorial > Start of Trail > Start of Lesson | Search |
The JDK1.1 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.
To illustrate, we will write a C program that invokes the Java Virtual
Machine and calls the Prog.main
method defined in Prog.java
:
The C code inpublic class Prog { public static void main(String[] args) { System.out.println("Hello World" + args[0]); } }
invoke.c
begins with a call to
JNI_GetDefaultJavaVMInitArgs
to obtain the default initialization
settings, such as heap size, stack size, and so on. It then calls
JNI_CreateJavaVM
to load and initialize the Virtual
Machine. JNI_CreateJavaVM
fills in two return values:
jvm
refers to the created Java Virtual Machine. You
can use this to destroy the Virtual Machine at a later time, for example.
env
is a JNI interface pointer that the current
thread can use to access Java features, such as calling a Java method.
JNI_CreateJavaVM
successfully returns, the current
native thread has bootstrapped itself into the Java Virtual Machine
and is therefore running just like a native method. The only
difference is that there is no concept of returning to the Java
Virtual Machine. Therefore, any local references
that you subsequently create will not be freed until you call DestroyJavaVM
.
Once you have created the Java Virtual Machine, you can issue
regular JNI calls to invoke, for example, Prog.main
. DestroyJavaVM
attempts to unload the Java Virtual Machine. (The JDK 1.1 Java
Virtual Machine cannot be unloaded; therefore DestroyJavaVM always
returns an error code.)
You need to compile and link invoke.c
with the Java libraries shipped
with JDK1.1. On Solaris, you can use the following command to compile
and link invoke.c
:
On Win32 with Microsoft Visual C++ 4.0, the command line is:cc -I<where jni.h is> -L<where libjava.so is> -ljava invoke.c
cl -I<where jni.h is> -MT invoke.c -link <where javai.lib is>\javai.lib
Those working in the MacOS environment should refer to the JManager API, which is part of the
MacOS Runtime for Java
.
You use the JManager API to embed Java applications into your application.
Run the resulting executable from the command line. It is possible that you may get the following error message:
This error message indicates that you have set the wrong value for theUnable to initialize threads: cannot find class java/lang/Thread Can't create Java VM
vm_args.classpath
variable.
You might get a different
system error indicating that it cannot find either libjava.so
(on Solaris) or javai.dll
(on
Win32). If this is the case, add libjava.so
into your LD_LIBRARY_PATH
on
Solaris, or add javai.dll
into your executable path on Win32.
The
program may report an error that it cannot find the class Prog
. If so, make sure the
directory containing Prog.class
is in the vm_args.classpath
variable as well.
Our example program, attach.c
, therefore, will only work on Win32.
This example program is a variation of invoke.c
. Instead of calling Prog.main
in the
main thread, the native code spawns five threads and then waits
for them to finish before it destroys the Java Virtual Machine. Each
thread attaches itself to the Java Virtual Machine, invokes the
Prog.main
method, and finally detaches itself from the Virtual Machine
before it terminates. Note that the third argument to AttachCurrentThread
is reserved and should be set to NULL
.
When you call DetachCurrentThread
, you free all local references belonging to the current thread.
read
, readv
, write
, writev
,
getmsg
, putmsg
, poll
, open
, close
, pipe
, fcntl
, dup
, create
, accept
,
recv
, send
, and so on. This may cause undesirable effects on a hosting
native application that also depends on these system calls.
AttachCurrentThread
simply fails on
Solaris (unless your code calls it from the main thread that created the
Virtual Machine).
DestroyJavaVM
call simply returns an error code.
![]() ![]() ![]() |
Start of Tutorial > Start of Trail > Start of Lesson | Search |