Java Reference
In-Depth Information
from native code. (The not-so-simple way is to explicitly construct a
Throwable
object and provide it a cause. Then use the JNI
Throw()
function.)
For special needs, you can define custom
Exception
classes in Java that
extend
java.lang.Exception
.Ifacustom exception can be found in the
CLASSPATH
, then
FindClass()
can find it and native code can throw the
custom exception just as well as the standard Java library exceptions.
22.11 Local and global references
The JVM must keep track of references to all Java objects passed to native code,
primarily so the Java garbage collector does not arbitrarily free an object while
it is in use in the native code. There are two basic types of references to objects
used by native code:
local
and
global
references.
Local references are valid only during the duration of the native method call.
They are freed automatically upon return from native code to Java. Global ref-
erences exist even after the native method goes out of scope. Global references
must be freed explicitly by the programmer when no longer needed.
All objects are passed to native code as local references, and all objects created
within the native code by JNI functions such as
NewStringUTF()
are created
as local references. This arrangement is normal and expected. When the native
method returns, the local references are deleted, permitting the garbage collector
to free the memory associated with those objects if needed (and, of course, if
there are no outstanding references still in use on the Java side).
For special needs, JNI permits you to create global references from local
references with the
NewGlobalRef()
function. If a global reference is created,
then it is vital that
DeleteGlobalRef()
be called when the global reference
is no longer needed. Otherwise, a memory leak and/or heap fragmentation can
occur as the Java garbage collector is never able to free or move the memory
associated with the global reference.
A tempting but mistaken tactic is to attempt to cache a
jclass
across native
method invocations in order to save the cost of the call to
GetObjectClass()
or
FindClass()
. Under normal circumstances, the
jclass
is a local reference
and so it becomes no longer valid after the first native method returns. An attempt
to use the cached value on a subsequent call to the native method produces
unpredicatable results, possibly including a JVM crash.
A related mistake is to attempt to cache method or field IDs, probably in an
attempt to save the cost of calling
GetMethodID()
or
GetFieldID()
.Itturns
out that method and field IDs are valid only as long as the class from which the
ID is derived is not unloaded. After a native method returns to Java code, the Java
garbage collector could possibly unload the class to which the IDs refer. If so,
then subsequent use of the cached IDs can result in unpredictable behavior.
To solve the latter problem it is safest to re-compute the field or method
IDs when needed again. Another solution is to create a global reference to the
jclass
that remains valid even after the native method goes out of scope. Since
Search WWH ::
Custom Search