RFR: 8233299: Implementation: JEP 365: ZGC on Windows
Stefan Karlsson
stefan.karlsson at oracle.com
Thu Oct 31 10:18:20 UTC 2019
Hi all,
Please review this patch to add ZGC support on Windows.
https://cr.openjdk.java.net/~stefank/8233299/webrev.01/
https://bugs.openjdk.java.net/browse/JDK-8233299
As mentioned in the JEP (https://openjdk.java.net/jeps/365), there were
some preparation patches that needed to go in to pave the way for this
patch:
8232601: ZGC: Parameterize the ZGranuleMap table size
8232602: ZGC: Make ZGranuleMap ZAddress agnostic
8232604: ZGC: Make ZVerifyViews mapping and unmapping precise
8232648: ZGC: Move ATTRIBUTE_ALIGNED to the front of declarations
8232649: ZGC: Add callbacks to ZMemoryManager
8232650: ZGC: Add initialization hooks for OS specific code
8232651: Add implementation of os::processor_id() for Windows
... they have all been pushed now.
One important key-point to this implementation is to use the new Windows
APIs that support reservation and mapping of memory through
"placeholders": VirtualAlloc2, VirtualFreeEx, MapViewOfFile3, and
UnmapViewOfFile2. These functions are available starting from version
1803 of Windows 10 and Windows Server. ZGC will lookup these symbols to
determine if the Windows version supports these functions.
Correlating the text in the JEP with the code:
* '"Support for multi-mapping memory". ZGC's use of colored pointers
requires support for heap multi-mapping, so that the same physical
memory can be accessed from multiple different locations in the process
address space. On Windows, paging-file backed memory provides physical
memory with an identity (a handle), which is unrelated to the virtual
address where it is mapped. Using this identity allows ZGC to map the
same physical memory into multiple locations.'
We commit memory via paging file mappings and map views into that memory.
The function ZMapper::create_and_commit_paging_file_mapping uses
CreateFileMappingW with SEC_RESERVE to create this mapping,
MapViewOfFile3 to map a temporary view into the mapping, VirtualAlloc2
to commit the memory, and then UnmapViewOfFile2 to unmap the view.
The reason to use SEC_RESERVE and the extra VirtualAlloc2, instead of
SEC_COMMIT, is to ensure that the later multi-mappings of committed file
mappings don't fail under low-memory situations. Earlier prototypes used
SEC_COMMIT and saw these kind of OOME errors when mapping new views to
already committed memory. The current platform-independent ZGC code
isn't prepared to handle OOME errors when mapping views, so we chose
this solution.
MapViewOfFile3 is then used to multi-map into the committed memory.
* '"Support for mapping paging-file backed memory into a reserved
address space". The Windows memory management API is not as flexible as
POSIX's mmap/munmap, especially when it comes to mapping file backed
memory into a previously reserved address space region. To do this, ZGC
will use the Windows concept of address space placeholders. The
placeholder concept was introduced in version 1803 of Windows 10 and
Windows Server. ZGC support for older versions of Windows will not be
implemented.'
Before the placeholder APIs there was no way to first reserve a specific
virtual memory range, and then map a view of a committed paging file
over that range. The VirtuaAlloc function could be used to first reserve
and then commit anonymous memory, but nothing similar existed for mapped
views. Now with placeholders, we can create a placeholder reservation of
memory with VirtualAlloc2, and then replace that reservation with
MapViewOfFile3. When memory is unmapped, we can use UnmapViewOfFile2 to
"preserve" the placeholder memory reservation.
* '"Support for mapping and unmapping arbitrary parts of the heap".
ZGC's heap layout in combination with its dynamic sizing (and re-sizing)
of heap pages requires support for mapping and unmapping arbitrary heap
granules. This requirement in combination with Windows address space
placeholders requires special attention, since placeholders must be
explicitly split/coalesced by the program, as opposed to being
automatically split/coalesced by the operating system (as on Linux).'
Half of the preparation patches were put in place to support this. When
replacing a placeholder with a view of the backing file, we need to
exactly match the address and size of a placeholder. Also, when
unmapping a view, we need to exactly match the address and size of the
view, and replace it with a placeholder.
To make it easier to map and unmap arbitrary parts of the heap, we split
reserved memory into ZGranuleSize-sized placeholders. So, whenever we
perform any of these operations, we know that any given memory range
could be dealt with as a number of granules.
When memory is reserved, but not mapped, it is registered in the
ZVirtualMemoryManager. It splits memory into granule-sized placholders
when reserved memory is fetched, and coalesces placeholders when
reserved memory is handed back.
* '"Support for committing and uncommitting arbitrary parts of the
heap". ZGC can commit and uncommit physical memory dynamically while the
Java program is running. To support these operations the physical memory
will be divided into, and backed by, multiple paging-file segments. Each
paging-file segment corresponds to a ZGC heap granule, and can be
committed and uncommitted independently of other segments.'
Just like we can map and unmap in granules, we want to be able to commit
and uncommit memory in granules. You can see how memory is committed and
uncommitted in granules in ZBackingFile::commit_from_paging_file and
ZBackingFile::uncommit_from_paging_file. Each committed granule is
associated with one registered handle. When memory for a granule is
uncommitted, the handle is closed. At this point, no views exist to the
mapping and the memory is handed back to the OS.
Final point about ZPhysicalMemoryBacking. We've tried to make this file
similar on all OSes, with the hope to be able to combine them when both
the Windows and macOS ports have been merged.
Thanks,
StefanK
More information about the hotspot-gc-dev
mailing list