RFR: Add NMT support for Java heap

Per Liden per.liden at oracle.com
Tue Dec 12 13:35:19 UTC 2017

On 2017-12-12 13:29, Aleksey Shipilev wrote:
> On 12/12/2017 01:06 PM, Per Liden wrote:
>> On 2017-12-12 12:28, Aleksey Shipilev wrote:
>>> But, this does look overly pessimistic thing to do. If there are multiple mappings that differ in
>>> upper bits, that means there is enough unused space between the mappings, and we don't actually have
>>> to reserve it?
> Whaat I meant is: instead of allocating [0x0001...0x0005], we can reserve [0x00010...0,
> 0x00010050..0], [0x00020...0, 0x00020050..0], [0x00030...0, 0x00030050..0], etc, where the size of
> each reserved chunk is -Xmx.
>> We actually do want to reserve it anyway, for two reasons.
>> 1) In ZGC, by having a heap address spare much larger than the heap size we are essentially immune
>> to address space fragmentation. I.e. we can always find a hole big enough for any allocation,
>> without the need to first compact the heap.
> Okay. I am quite a bit blurry on compaction that ZGC does. Does this mean the relocation phase
> temporarily allocates target pages outside of currently reserved slice taken by Java heap? And you
> want to have enough spare so that you always have contiguous virtual memory to allocate that
> temporary excess at?

What I meant above was just that in GCs which have a 1:1 mapping between 
heap address space and max heap size, you can run into a situation where 
you have say 32M of free memory (or address space, same thing in that 
context) on the heap, but it's scattered across say 8 chunks 4M each, 
which means you'd need to compact before you can allocate an 32M object. 
In ZGC, we can instead just map (or remap) that 32M to some other 
location in the heap address space.

About compaction. ZGC relocates/compacts to pages inside the heap. The 
algorithm allows for in-place compaction, in which case no additional 
pages are needed. However, in the current implementation, we typically 
need one free page per GC worker thread to do relocation. When all 
objects in a given page have been relocated, that page immediately 
becomes reusable, either for new Java thread allocations, or for further 
GC worker relocation allocations.

Btw, when I say "page" here I mean ZPage, which is conceptually similar 
to a HeapRegion in G1/Shanandoah.

> If so, you can allocate another -Xmx-sized chunk, without always reserving
> terabytes of space, right?
>> 2) CollectedHeap::is_in_reserved() is often used as a inexpensive check if something point into the
>> heap. By reserving all addresses in all heap views this check remains inexpensive as we know that
>> some other random mmap() call in the VM didn't end up in-between two heap views.
> is_in_reserved() is the compelling argument. Although you can probably just mask out high-bits and
> land in the first mapping. The mappings of the same size would make this work.
>> This is also very useful when debugging. For example, when dumping memory or looking at stack
>> traces you can easily see if something is an oop or not (oops always start with 0x00001...,
>> 0x000008... or 0x000004...).
> Yes, this does not go away: the starts of each reserved chunk stays the same.

Unless all of that address space is reserved you can no longer be sure 
that those addresses are actually oops. They could just as well be 
native pointers, because some other part of the JVM could have mmap:ed 
something there.


> Thanks,
> -Aleksey

More information about the zgc-dev mailing list