Contents | Prev | Next | Java Native Interface Specification |
The Invocation API allows software vendors to load the Java VM* into an arbitrary native application. Vendors can deliver Java-enabled applications without having to link with the Java VM source code.
This chapter begins with an overview of the Invocation API. This is followed by reference pages for all Invocation API functions.
To enhance the embeddability of the Java VM, the Invocation API is extended in JDK 1.1.2 in a few minor ways.
Main.test
. For clarity, we omit error checking.
#include <jni.h> /* where everything is defined */ ... JavaVM *jvm; /* denotes a Java VM */ JNIEnv *env; /* pointer to native method interface */ JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */ vm_args.version = 0x00010001; /* New in 1.1.2: VM version */ /* Get the default initialization arguments and set the class * path */ JNI_GetDefaultJavaVMInitArgs(&vm_args); vm_args.classpath = ...; /* load and initialize a Java VM, return a JNI interface * pointer in env */ JNI_CreateJavaVM(&jvm, &env, &vm_args); /* invoke the Main.test method using the JNI */ jclass cls = env->FindClass("Main"); jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V"); env->CallStaticVoidMethod(cls, mid, 100); /* We are done. */ jvm->DestroyJavaVM();This example uses three functions in the API. The Invocation API allows a native application to use the JNI interface pointer to access VM features. The design is similar to Netscape's JRI Embedding Interface.
JNI_CreateJavaVM()
function loads and initializes a Java VM and
returns a pointer to the JNI interface pointer. The thread that called
JNI_CreateJavaVM()
is considered to be the main thread.
JNIEnv
) is valid only in the current thread. Should
another thread need to access the Java VM, it must first call
AttachCurrentThread()
to attach itself to the VM and obtain a JNI interface
pointer. Once attached to the VM, a native thread works just like an ordinary
Java thread running inside a native method. The native thread remains
attached to the VM until it calls DetachCurrentThread()
to detach itself.
The attached thread should have enough stack space to perform a reaonable amount of work.
The allocation of stack space per thread is operating system-specific. For example,
using pthreads, the stack size can be specified in the pthread_attr_t
argument
to pthread_create
.
DestroyJavaVM()
to unload the entire VM.
The VM waits until the main thread is the only user thread before it actually unloads. User threads include both Java threads and attached native threads. This restriction exists because a Java thread or attached native thread may be holding system resources, such as locks, windows, and so on. The VM cannot automatically free these resources. By restricting the main thread to be the only running thread when the VM is unloaded, the burden of releasing system resources held by arbitrary threads is on the programmer.
Different Java VM implementation will likely require different
initialization arguments. It is difficult to come up with a standard
initialization structure suitable for all present and future Java
VMs. As a compromise, we reserve the first field
(version
) to identify the content of the initialization
structure. Native applications embedding JDK 1.1.2 must set the
version field to 0x00010001
. VM implementations are
encouraged to use the same initialization structure as JDK, although
other implementations may choose to ignore some of the initialization
arguments supported by JDK.
Version numbers 0x80000000
to 0xFFFFFFFF
are
reserved, and should not be recognized by any VM implementation.
The following code shows the structure used to initialize the Java VM in JDK 1.1.2.
typedef struct JavaVMInitArgs { /* The first two fields were reserved in JDK 1.1, and formally introduced in JDK 1.1.2. */ /* Java VM version */ jint version; /* System properties. */ char **properties; /* whether to check the Java source files are newer than * compiled class files. */ jint checkSource; /* maximum native stack size of Java-created threads. */ jint nativeStackSize; /* maximum Java stack size. */ jint javaStackSize; /* initial heap size. */ jint minHeapSize; /* maximum heap size. */ jint maxHeapSize; /* controls whether Java byte code should be verified: * 0 -- none, 1 -- remotely loaded code, 2 -- all code. */ jint verifyMode; /* the local directory path for class loading. */ const char *classpath; /* a hook for a function that redirects all VM messages. */ jint (*vfprintf)(FILE *fp, const char *format, va_list args); /* a VM exit hook. */ void (*exit)(jint code); /* a VM abort hook. */ void (*abort)(); /* whether to enable class GC. */ jint enableClassGC; /* whether GC messages will appear. */ jint enableVerboseGC; /* whether asynchronous GC is allowed. */ jint disableAsyncGC; /* Three reserved fields. */ jint reserved0; jint reserved1; jint reserved2; } JDK1_1InitArgs;In JDK 1.1.2, the initialization structure provides hooks so that a native application can redirect VM messages and obtain control when the VM terminates.
The structure below is passed as an argument when a native thread attaches to
a Java VM in JDK 1.1.2. In actuality, no arguments are required for a native
thread to attach to the JDK 1.1.2. The JDK1_1AttachArgs
structure consists
only of a padding slot for those C compilers that do not permit empty
structures.
typedef struct JDK1_1AttachArgs { /* * JDK 1.1 does not need any arguments to attach a * native thread. The padding is here to satisfy the C * compiler which does not permit empty structures. */ void *__padding; } JDK1_1AttachArgs;
JavaVM
type is a pointer to the Invocation API function table. The
following code example shows this function table.
typedef const struct JNIInvokeInterface *JavaVM; const struct JNIInvokeInterface ... = { NULL, NULL, NULL, DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, };Note that three Invocation API functions,
JNI_GetDefaultJavaVMInitArgs()
, JNI_GetCreatedJavaVMs(), and
JNI_CreateJavaVM()
, are not part of the JavaVM function table. These
functions can be used without a preexisting JavaVM
structure.
jint JNI_GetDefaultJavaVMInitArgs(void *vm_args);
Returns a default configuration for the Java VM. Before calling this
function, native code must set the vm_args->version
field
to the JNI version it expects the VM to support. In JDK 1.1.2,
vm_args->version
must be set to
0x00010001
.
(JDK 1.1 did not require the native code to set the version field. For
backward compatibility, JDK 1.1.2 assumes that the requested version
is 0x00010001 if the version field is not set. Future versions of JDK
will require the version field to be set to an appropriate value.)
After this function returns,
vm_args->version
will be set to the actual JNI version
the VM supports.
vm_args
: a pointer to a VM-specific initialization
structure in to which the
default arguments are filled.
jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen,
jsize *nVMs);
Returns all Java VMs that have been created. Pointers to VMs are written in the buffer vmBuf in the order they are created. At most bufLen number of entries will be written. The total number of created VMs is returned in *nVMs.
JDK 1.1 does not support creating more than one VM in a single process.
vmBuf
: pointer to the buffer where the VM structures will be placed.
bufLen
: the length of the buffer.
nVMs
: a pointer to an integer.
jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env,
void *vm_args);
Loads and initializes a Java VM. The current thread becomes the main thread.
Sets the env
argument to the JNI interface pointer of the main thread.
The JDK does not support creating more than one VM in a single process. The version field in vm_args must be set to 0x00010001
.
p_vm
: pointer to the location where the resulting VM structure will be placed.
p_env
: pointer to the location where the JNI interface pointer for the main
thread will be placed.
vm_args
: Java VM initialization arguments.
jint DestroyJavaVM(JavaVM *vm);
Unloads a Java VM and reclaims its resources. Only the main thread can
unload the VM. The main thread must be the only remaining user thread when
it calls DestroyJavaVM()
.
vm
: the Java VM that will be destroyed.
JDK 1.1.2 does not support unloading the VM.
jint AttachCurrentThread(JavaVM *vm, JNIEnv **p_env,
void *thr_args);
Attaches the current thread to a Java VM. Returns a JNI interface pointer in the
JNIEnv
argument.
Trying to attach a thread that is already attached is a no-op.
A native thread cannot be attached simultaneously to two Java VMs.
When a thread is attached to the VM, the context class loader is the bootstrap loader.
vm
: the VM to which the current thread will be attached.
p_env
: pointer to the location where the JNI interface pointer of the current
thread will be placed.
thr_args
: VM-specific thread attachment arguments.
jint DetachCurrentThread(JavaVM *vm);
Detaches the current thread from a Java VM. All Java monitors held by this thread are released. All Java threads waiting for this thread to die are notified.
The main thread, which is the thread that created the Java VM, cannot be
detached from the VM. Instead, the main thread must call
JNI_DestroyJavaVM()
to unload the entire VM.
vm
: the VM from which the current thread will be detached.
*As used on this web site, the term "Java VM" means a virtual machine for the Java platform.
Java Native Interface Specification (HTML generated by dkramer on March 15, 1997)
Copyright © 1996, 1997 Sun Microsystems, Inc.
All rights reserved
Please send any comments or corrections to jni@java.sun.com