Electrical FireDesignRuntimeMonitors and Hash Codes |
|
Each Java object contains a monitor and a hash code. The object's monitor
is acquired by entering a synchronized method invoked on the
object or by entering a Java synchronized statement on that
object. The object's monitor is released by leaving the synchronized
method or synchronized statement. Finally, the wait
method also releases and reacquires an object's monitor.
A thread can acquire the same monitor multiple times; the thread must
release the monitor the same number of times before another thread can acquire
the monitor. A thread that attempts to acquire a monitor held by another
thread blocks until that monitor becomes available or until the waiting
thread is stopped using Thread.stop.
In the Java source language all synchronization operations are balanced -- each object acquisition must be balanced by a release of the same object. This is enforced by Java's block structuring.
On the other hand, Java class files can contain unstructured monitorenter
and monitorexit bytecodes that acquire an object without releasing
it or release one without acquiring it. To simplify our implementation the
front end will analyze the bytecodes of a method and throw a verification
error if it cannot determine that monitorenter and monitorexit
calls are properly structured. Doing the precise analysis would be equivalent
to solving the halting problem, so the front end does a conservative control
and data graph analysis that ensures that:
monitorenter and monitorexit
bytecodes in a method can be divided into a set of disjoint subsets S1, S2, ..., Sn.
monitorenter and monitorexit bytecodes
in a subset Si refer to the same data node when the
method is translated into the static single assignment form.
monitorenter
bytecode Ei.
monitorexit bytecode Xij in
subset Si is dominated by Si's
monitorenter bytecode Ei.
monitorexit
bytecode in Si.
monitorexit bytecode in Si.
Every program that satisfies the above conditions has block-structured
monitor usage. The converse is not necessarily true -- there are some programs
that use monitorenter and monitorexit in a structured
manner that do not satisfy the above conditions. It is our hope and expectation
that Java-to-bytecode compilers will not produce such programs, as they
would have to be rejected by our verifier. Current Java-to-bytecode compilers
do not seem to produce such programs.
Each Java object has a 32-bit integer hash code returned by the hashCode
method. Hash codes are meant to be statistically distinct object identifiers.
For some classes such as String the Java specification gives
the value that the hashCode method should produce. For other
classes the value is implementation-defined.
We implement monitors and hash codes differently depending on whether we are working on a 32 or 64-bit address implementation. See the 32-bit implementation and 64-bit implementation pages.