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 JNI has corresponding methods MonitorEnter and MonitorExit. The corresponding CNI macros are JvMonitorEnter and JvMonitorExit.

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 the block is abnormally terminated by an exception, which means there is an implicit try-finally.

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); }
};
The equivalent of Java's:
synchronized (OBJ) { CODE; }
can be simply expressed:
{ 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 synchornized method.