Next: Invocation, Previous: Exception Handling, Up: About CNI
Each Java object has an implicit monitor.
The Java VM uses the instruction monitorenter
to acquire
and lock a monitor, and monitorexit
to release it.
The corresponding CNI macros are JvMonitorEnter
and
JvMonitorExit
(JNI has similar methods MonitorEnter
and MonitorExit
).
The Java source language does not provide direct access to these primitives.
Instead, there is a synchronized
statement that does an
implicit monitorenter
before entry to the block,
and does a monitorexit
on exit from the block.
Note that the lock has to be released even when the block is abnormally
terminated by an exception, which means there is an implicit
try finally
surrounding synchronization locks.
From C++, it makes sense to use a destructor to release a lock. CNI defines the following utility class:
class JvSynchronize() { jobject obj; JvSynchronize(jobject o) { obj = o; JvMonitorEnter(o); } ~JvSynchronize() { JvMonitorExit(obj); } };
So this Java code:
synchronized (OBJ) { CODE }
might become this C++ code:
{ JvSynchronize dummy (OBJ); CODE; }
Java also has methods with the synchronized
attribute.
This is equivalent to wrapping the entire method body in a
synchronized
statement.
(Alternatively, an implementation could require the caller to do
the synchronization. This is not practical for a compiler, because
each virtual method call would have to test at run-time if
synchronization is needed.) Since in gcj
the synchronized
attribute is handled by the
method implementation, it is up to the programmer
of a synchronized native method to handle the synchronization
(in the C++ implementation of the method).
In other words, you need to manually add JvSynchronize
in a native synchronized
method.