The default Garbage Collection (GC) policy for the Eclipse OpenJ9 Virtual Machine (J9VM), which powers the IBMÂ® SDK, JavaTM Technology Edition, is generational concurrent (gencon). The gencon policy subdivides the Java heap into two regions known as nursery and tenured regions. The nursery region is further divided into two spaces known as allocate and survivor spaces. Objects are allocated in the allocate space of the nursery. As this space fills up, live objects are evacuated to the survivor space in a process known as scavenge. The roles of the allocate and survivor spaces are then swapped. If objects survive a certain number of nursery collections, they are promoted to the tenured region. For a majority of Java applications, most objects are short-lived. This means that nursery collections can reclaim short-lived objectsâ memory efficiently without having to collect the entire heap. Long-lived objects that have been promoted to the tenured region are collected less frequently, yielding a better return on investment in reclaimed memory for time spent in GC.
Concurrent Scavenge is a feature of the GC in J9VM, specifically under the gencon GC policy, which aims to minimize the time spent in âstop-the-worldâ pauses by performing the scavenge phase while the Java application threads are running. At the start of a scavenge cycle, application threads are suspended briefly to copy live objects referenced in static objects, stack slots, and registers. Application threads are resumed, along with GC threads, which can begin evacuating live objects from the allocate space to the survivor space. Any load of object references by the application threads must go through a Read Barrier, which determines whether the value being loaded is within the allocate space. A reference to the allocate space is either:
- a reference to a live object that has yet to be relocated to the survivor space
- a stale reference to the original location of a live object that has already been evacuated by the GC
In such a scenario, the referenced object is then migrated to the survivor space if necessary, and the reference is updated. The process continues until all live objects have been evacuated to the survivor space. At the end of the cycle, application threads are suspended briefly again for cleanup, bookkeeping, and to swap the allocate and survivor spaces.
Any software implementation of a Read Barrier would be extremely slow since every object reference load would be prefaced with a check of whether that object is in the allocate space. So, J9VM uses a hardware implementation of the Read Barrier. The Guarded Storage (GS) Facility is a feature of the IBM z14TM (z14) Mainframe that allows a program to guard regions in memory such that performing a guarded load of a reference to that region triggers a user defined interrupt handler. The nursery area is mapped and registered to the facility as the guarded-storage area. The hardware subdivides this area into 64 sections, and provides a masking capability to selectively enable a subset of these 64 sections to be guarded. At the start of a scavenge cycle, the mask corresponding to the allocate space of the nursery is selectively enabled. During the cycle, any object references loaded by the application threads are done so using a new set of guarded load instructions. When the hardware executes a guarded load instruction, if the guarded storage facility is enabled, it determines whether the value being loaded is part of any of the active guarded sections, which the GC has ensured correspond to the allocate space. If the value is part of a guarded region, the GS facility triggers a trap that is handled by an interrupt handler which migrates the referenced object to the survivor space if necessary, and updates the reference. At the end of the scavenge cycle, the guarded storage facility is disabled across all threads.