Next: , Previous: Exception Handling, Up: About CNI


10.13 Synchronization

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.