JNI will be enhanced in 1.2 to:
The changes are driven by licensee and user comments. Please continue to send your comments, suggestions, and concerns to jni@java.sun.com.
FindClass
has been extended
so that it finds classes loaded with a class loader.
jclass FindClass(JNIEnv *env, const char *name);
In JDK 1.1,
FindClass
searched only local classes inCLASSPATH
. The resulting classes did not have a class loader.The Java security model has been extended to allow non-system classes to load and call native methods. In JDK 1.2,
FindClass
locates the class loader associated with the current native method. If the native code belongs to a system class, no class loader will be involved. Otherwise, the proper class loader will be invoked to load and link the named class.
In JDK 1.2, each class loader manages its own set of native libraries. The same JNI native library cannot be loaded into more than one class loader. The benefits of the new approach are:
To facilitate versioning control and resource management, JNI libraries in 1.2 may optionally export the following two functions:
jint JNI_OnLoad(JavaVM *vm, void *reserved);
The VM callsJNI_OnLoad
when the native library is loaded (for example, throughSystem.loadLibrary
).JNI_OnLoad
must return the JNI version needed by the native library.In order to use any of the new 1.2 JNI functions, a native library must export a
JNI_OnLoad
function that returns0x00010002
. If the native library does not export aJNI_OnLoad
function, the VM assumes that the library only requires JNI version0x00010001
. If the VM does not recognize the version number returned byJNI_OnLoad
, the native library cannot be loaded.
void JNI_OnUnload(JavaVM *vm, void *reserved);
The VM calls JNI_OnUnload
when the class loader
containing the native library is garbage collected. This function can
be used to perform cleanup operations. Because this function is called
in an unknown context (such as from a finalizer), the programmer
should be conservative on using Java VM services, and refrain from
arbitrary Java call-backs.
Note that JNI_OnLoad
and JNI_OnUnload
are
two functions optionally supplied by JNI libraries, not exported from
the VM.
JDK 1.1 provides a DeleteLocalRef
function so that
programmers can manually delete local references. For example, if
native code iterates through a potentially large array of objects and
uses one element in each iteration, it is a good practice to delete
the local reference to the no-longer-used array element before a new
local reference is created in the next iteration.
JDK 1.2 provides an additional set of functions for local reference lifetime management.
jint EnsureLocalCapacity(JNIEnv *env, jint capacity);
Ensures that at least a given number of local references can be created in the current thread. Returns 0 on success; otherwise returns a negative number and throws an
OutOfMemoryError
.Before it enters a native method, the VM automatically ensures that at least 16 local references can be created.
For backward compatibility, the VM allocates local references beyond the ensured capacity. (As a debugging support, the VM may give the user warnings that too many local references are being created. In JDK 1.2, the programmer can supply the
-verbose:jni
command line option to turn on these messages.) The VM callsFatalError
if no more local references can be created beyond the ensured capacity.
jint PushLocalFrame(JNIEnv *env, jint capacity);
Creates a new local reference frame, in which at least a given number of local references can be created. Returns 0 on success, a negative number and a pending
OutOfMemoryError
on failure.
jobject PopLocalFrame(JNIEnv *env, jobject result);
Pops off the current local reference frame, frees all the local references, and returns a local reference in the previous local reference frame for the given
result
object.Pass
NULL
asresult
if you do not need to return a reference to the previous frame.
jobject NewLocalRef(JNIEnv *env, jobject ref);
Creates a new local reference that refers to the same object asref
. The givenref
may be a global or local reference. ReturnsNULL
ifref
refers tonull
.
NULL
. Programmers can detect
whether a weak global reference points to a freed object by using
IsSameObject
to compare the weak reference against
NULL
.
Weak global references in JNI are a simplified version of the Java
Weak References, available as part of the core 1.2 API (
java.lang.Ref
and its related classes).
jweak NewWeakGlobalRef(JNIEnv *env, jobject obj);
Creates a new weak global reference. ReturnsNULL
ifobj
refers tonull
, or if the VM runs out of memory. If the VM runs out of memory, anOutOfMemoryError
will be thrown.
void DeleteWeakGlobalRef(JNIEnv *env, jweak obj);
Delete the VM resources needed for the given weak global reference.
In JDK 1.1, programmers can use
Get/Release
functions to
obtain a pointer to primitive array elements. If the VM supports
pinning, the pointer to the original data is returned; otherwise, a
copy is made.
New 1.2 functions allow native code to obtain a direct pointer to array elements even if the VM does not support pinning.
void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy);
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode);
The semantics of these two functions are very similar to the existingGet/Release
functions. If possible, the VM returns a pointer to the primitive array; otherwise, a copy is made. However, there are significant restrictions on how these functions can be used.ArrayElements After calling
GetPrimitiveArrayCritical
, the native code should not run for an extended period of time before it callsReleasePrimitiveArrayCritical
. We must treat the code inside this pair of functions as running in a "critical region." Inside a critical region, native code must not call other JNI functions, or any system call that may cause the current thread to block and wait for another Java thread. (For example, the current thread must not callread
on a stream being written by another Java thread.)These restrictions make it more likely that the native code will obtain an uncopied version of the array, even if the VM does not support pinning. For example, a VM may temporarily disable garbage collection when the native code is holding a pointer to an array obtained via
GetPrimitiveArrayCritical
.Multiple pairs of
GetPrimtiveArrayCritical
andReleasePrimitiveArrayCritical
may be nested. For example:jint len = (*env)->GetArrayLength(env, arr1); jbyte *a1 = (*env)->GetPrimitiveArrayCritical(env, arr1, 0); jbyte *a2 = (*env)->GetPrimitiveArrayCritical(env, arr2, 0); /* We need to check in case the VM tried to make a copy. */ if (a1 == NULL || a2 == NULL) { ... /* out of memory exception thrown */ } memcpy(a1, a2, len); (*env)->ReleasePrimitiveArrayCritical(env, arr2, a2, 0); (*env)->ReleasePrimitiveArrayCritical(env, arr1, a1, 0);
Note that GetPrimitiveArrayCritical
might still make a copy
of the array if the VM internally represents arrays in a different format.
Therefore we need to check its return value against NULL
for
possible out of memory situations.
void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
Copieslen
number of Unicode characters beginning at offsetstart
to the given bufferbuf
.Throws
StringIndexOutOfBoundsException
on index overflow.
void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
Translateslen
number of Unicode characters beginning at offsetstart
into UTF-8 format and place the result in the given bufferbuf
.Throws
StringIndexOutOfBoundsException
on index overflow.
const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy);
void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray);
The semantics of these two functions are similar to the existingGet/ReleaseStringChars
functions. If possible, the VM returns a pointer to string elements; otherwise, a copy is made. However, there are significant restrictions on how these functions can be used. In a code segment enclosed byGet/ReleaseStringCritical
calls, the native code must not issue arbitrary JNI calls, or cause the current thread to block.The restrictions on
Get/ReleaseStringCritical
are similar to those onGet/ReleasePrimitiveArrayCritical
.
Programmers can use the JNI to call Java methods or access Java fields if they know the name and type of the methods or fields. The Java Core Reflection API allows programmers to introspect Java classes at runtime. JNI provides a set of conversion functions between field and method IDs used in the JNI to field and method objects used in the Java Core Reflection API.
jmethodID FromReflectedMethod(JNIEnv *env, jobject method);
Converts ajava.lang.reflect.Method
orjava.lang.reflect.Constructor
object to a method ID.
jfieldID FromReflectedField(JNIEnv *env, jobject field);
Converts a java.lang.reflect.Field
to a field ID.
jobject ToReflectedMethod(JNIEnv *env, jclass cls,
jmethodID methodID);
Converts a method ID derived fromcls
to ajava.lang.reflect.Method
orjava.lang.reflect.Constructor
object.Throws
OutOfMemoryError
and returns 0 if fails.
jobject ToReflectedField(JNIEnv *env, jclass cls,
jfieldID fieldID);
Converts a field ID derived fromcls
to ajava.lang.reflect.Field
object.Throws
OutOfMemoryError
and returns 0 if fails.
jint JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
In JDK 1.1, the second argument toJNI_CreateJavaVM
is always a pointer toJNIEnv *
. The third argument is a pointer to a JDK 1.1 specific structure (JDK1_1InitArgs
). TheJDK1_1InitArgs
structure is clearly not designed to be portable on all VMs.In JDK 1.2, we introduce a standard VM initialization structure. Backward compatibility is preserved. If the VM initialization argument points to a
JDK1_1InitArgs
structure,JNI_CreateJavaVM
still returns the 1.1 version of JNI interface pointer. The VM returns the 1.2 version of JNI interface pointer if the third argument points to aJavaVMInitArgs
structure. UnlikeJDK1_1InitArgs
, which contains a fixed set of options,JavaVMInitArgs
uses symbolic name/value pairs to encode arbitrary VM start up options.typedef struct JavaVMInitArgs { jint version; jint nOptions; JavaVMOption *options; jint *result; } JavaVMInitArgs;Theversion
field must be set to0x00010002
. (In contrast, the version field inJDK1_1InitArgs
must be set to0x00010001
.)Theoptions
field is an array of name/value pairs:typedef struct JavaVMOption { char *name; union { jint i; jdouble d; void *p; } value; } JavaVMOption;The size of the array is denoted by the nOptions field inJavaVMInitArgs
. Theresult
field may be set of NULL, or may be set to an integer array of sizenOptions
. When theresult
array is not NULL, the VM fills in the array one of the three values:
JNI_OK
Valid option JNI_UNRECOGNIZED
Unrecognized option JNI_ILLEGAL
Recognized option with illegal value
JNI_CreateJavaVM
returnsJNI_ERR
as soon as it encounters an illegal option. Unrecognized options are marked in theresult
array, but are otherwise ignored. All Java VMs must recognize the following set of standard options:
name value classpath
A string representing the system class path properties
A array of strings of the format: "name=value" verbose
A string composed of names separated by comma (" ,
"). The names indicate what kind of messages will be printed by the VM. For example, "gc,class
" instructs the VM to print GC and class loading related messages. Standard names include:gc
,class
, andjni
. All nonstandard (VM-specific) names must begin with "_
".vfprintf
Pointer to the vfprintf
hook.exit
Pointer to the exit
hook.abort
Pointer to the abort
hook.In addition, each VM implementation may support its own set of non-standard VM options. Non-standard option names must begin with an underscore ("_"). For example, JDK 1.2 supports
_ms
and_mx
options to allow programmers specify the initial and maximum heap size.Here is the example code that creates a Java VM with a given class path:
JavaVMOption options[1]; JavaVMInitArgs vm_args; /* Set up the options */ options[0].name = "classpath"; options[0].value.p = "c:\\java\\lib\\classes.zip;d:\\myclasses"; vm_args.version = 0x00010002; vm_args.options = options; vm_args.nOptions = 1; vm_args.result = NULL; /* Note that in JDK 1.2, there is no longer any need to call * JNI_GetDefaultJavaVMInitArgs. */ res = JNI_CreateJavaVM(&vm, &env, vm_args); if (res < 0) ...
jint AttachCurrentThread(JavaVM *vm, void **penv, jint version);
In JDK 1.1, the second argument toAttachCurrentThread
is always a pointer toJNIEnv
. The third argument toAttachCurrentThread
was reserved.In JDK 1.2, the third argument specifies the version of JNI function table returned in the second argument. The valid versions in JDK 1.2 are
0x00010001
(for 1.1) and0x00010002
(for 1.2).
jint DetachCurrentThread(JavaVM *vm);
In JDK 1.1, the main thread cannot be detached from the VM. It must callDestroyJavaVM
to unload the entire VM.In JDK 1.2, the main thread can be detached from the VM.
jint DestroyJavaVM(JavaVM *vm);
The support forDestryJavaVM
was not complete in 1.1. Only the main thread may callDestroyJavaVM
. The VM waits until the main thread is the only user-level thread and returns an error code.JDK 1.2 still does not support VM unloading. There is a slight relaxation to the use of
DestroyJavaVM
, however. Any thread may callDestroyJavaVM
. The VM waits until the current thread is the only user thread before it returns an error code.
jboolean IsAttached(JavaVM *vm);
ReturnsJNI_TRUE
if the current thread is attached to the VM, otherwise, returnsJNI_FALSE
.