• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Monitor inflation and the monitor pool
2--------------------------------------
3
4Every Java object conceptually has an associated monitor that is used to implement `synchronized`
5blocks as well as `Object.wait()` and related functionality. Initially, the state of this monitor
6is represented by the 32-bit `LockWord` in every object. This same word is also used to represent
7the system hash code if one has been computed for the object. See `lock_word.h` for details.
8
9The `LockWord` suffices for representing the state of unlocked objects with no waiters, whether or
10not they have a system hash code. It can also represent a locked (via a `synchronized` block)
11object that has neither a system hash code, nor an `Object.wait()` waiter. In all other cases, the
12lock must be "inflated". In that case, the `LockWord` contents reflect the "fat lock" state, and
13it contains primarily a `MonitorId`. We also inflate significantly contended locks, since the lock
14word itself does not have space for a wait queue or the like.
15
16(With the Concurrent Copying garbage collector, the `LockWord` supports another "forwarding
17address" state. In that case the above information is instead contained in the `LockWord` for the
18to-space objects referenced by the forwarding address.)
19
20MonitorIds
21----------
22A `MonitorId` is logically a pointer to a `Monitor` structure. The `Monitor` data structure is
23allocated when needed, and holds all the data needed to support any hashcode or `Object`
24synchronization operation provided by Java. On 32-bit implementations, it is essentially a
25pointer, except for some shifting and masking to avoid collisions with a few bits in the lock word
26required for other purposes. In a 64-bit environment, the situation is more complicated, since we
27don't have enough bits in the lock word to store a 64-bit pointer.
28
29In the 64-bit case, `Monitor`s are stored in "chunks" of 4K bytes. The bottom bits of a
30`MonitorId` are the index of the `Monitor` within its chunk. The remaining bits are used to find
31the correct chunk.
32
33Continuing with the 64-bit case, chunk addresses are stored in the `monitor_chunks_` data
34structure, which is logically a two-dimensional, vaguely triangular, array of pointers to chunks
35Each row is allocated separately, and twice as long as the previous one. (Thus the array is not
36really triangular.) The high bits of a `MonitorId` are interpreted as row- and column-indices into
37this array. Both the second level "rows" of this array, and the chunks themselves are allocated on
38demand.  By making the rows grow exponentially in size, and keeping a free list of recycled
39`Monitor` slots, we can accommodate a large number of `Monitor`s, without ever allocating more than
40twice the index size that was actually required.  (This doesn't count the top-level index needed
41to find the rows, but exponential growth of the rows makes that tiny.) And there is no need to
42ever move `Monitor` objects, which would significantly complicate the logic.
43
44The above data structure is distinct from the `MonitorList` data structure, which is used simply
45to enumerate all monitors. (It might be possible to save a bit of space in the 64-bit case, and
46have the `monitor_chunks_` data structure handle this as well.)
47
48Monitor inflation
49-----------------
50Monitors are inflated, and `Monitor` structs are allocated on demand, when an operation is
51performed that cannot be accommodated with just the lock word. This normally happens when we need
52to store a hash code in a locked object, when there is lock contention, or when `Object.wait` is
53executed. (Notification on an object with no waiters is trivial and does not require inflation.)
54In the 64-bit case, the `monitor_chunks_` data structure may also need to be extended at this time
55to allow mapping of an additional `MonitorId`.
56
57If we have to inflate a lock that is currently held by another Thread B, we must suspend B while
58updating the data structure representing the lock B holds. When the lock is later released by B,
59it will notice the change and operate on the fat lock representation instead.
60
61Monitor deflation
62-----------------
63Monitors are deflated, and the `Monitor` structs associated with deflated monitors are reclaimed
64as part of `Heap::Trim()` by invoking `SweepMonitorList()` with an `IsMarkedVisitor` that deflates
65unheld monitors with no waiters. This is done with all other threads suspended.
66
67Monitors are also reclaimed, again via `SweepMonitorList()`, in `SweepSystemWeaks()`, if the
68corresponding object was not marked.
69
70(There is one other use of monitor deflation from `ImageWriter`. That does not maintain
71`MonitorList`. It relies on the fact that the dex2oat process is single-threaded, and the heap is
72about to be discarded.)
73
74