RFR: 8034852: Shrinking of Metaspace high-water-mark causes incorrect OutOfMemoryErrors or back-to-back GCs

Erik Helin erik.helin at oracle.com
Mon May 5 14:06:52 UTC 2014


Hi Jon,

thanks for having a look at the patch!

On 2014-05-01 19:34, Jon Masamitsu wrote:
> Erik,
>
> Change looks good.

Thanks!

On 2014-05-01 19:34, Jon Masamitsu wrote:
> Please add a comment explaining why we're using committed now and why
> capacity did not work.  Basically an abbreviated version of your
> explanation
> below.

The old code in compute_new_size was the last code in metaspace making 
use of "capacity" as a concept. My idea was to remove "capacity" 
completely from the metaspace code after this change.

Do you think that we still should add a comment discussing a concept
(capacity) that the code no longer will use? Is there a possibility
that people that are new to the code will become confused?

Thanks,
Erik

On 2014-05-01 19:34, Jon Masamitsu wrote:
> Thanks.
>
> Jon
>
> On 4/30/2014 4:18 AM, Erik Helin wrote:
>> Hi all,
>>
>> this patch solves a rather tricky problem with the sizing of Metaspace.
>>
>> The issue happens when the GC threshold for Metaspace (called
>> "capacity_until_GC" in the code) becomes less than the committed
>> memory for Metaspace. Any calls to Metaspace::allocate that requires
>> committing more memory will then fail in
>> MetaspaceGC::allowed_expansion, because capacity_until_GC() <
>> MetaspaceAux::committed_memory(). The effect will be a
>> full GC and after the GC we try to expand and allocate. After the
>> expansion and before the allocation, one of two things can happen:
>>  1. capacity_until_GC is larger than the committed memory after the
>>     expansion. The allocation will now succeed, but the next allocation
>>     requiring a new chunk will *again* trigger a full GC. This pattern
>>     will repeat itself for each new allocation request requiring a new
>>     chunk.
>>  2. capacity_until_GC is still less than the committed memory even
>>     after the expansion. We throw a Java OOME (incorrectly).
>>
>> How can the GC threshold for Metaspace be less than the committed
>> memory? The problem is that MetaspaceGC::compute_new_size uses the field
>> _allocated_capacity for describing the amount of memory in Metaspace
>> that is "in use". _allocated_capacity does not consider the memory in
>> the chunk free lists to be "in use", since memory in the chunk free
>> lists are supposed to be available for new allocations. The problem is
>> that the chunk free lists can become fragmented, and then the memory
>> is not available for all kinds of allocations.
>>
>> This patch change MetaspaceGC::compute_new_size to use
>> MetaspaceAux::committed_memory for describing how much memory that is
>> "in use". The effect will be that memory in the chunk free lists will no
>> longer be considered "in use" (but will of course be used for future
>> allocations where possible). This will prevent capacity_until_GC from
>> shrinking below the committed memory "by definiton", since
>> capacity_until_GC can't be lower than the memory that is "in use".
>>
>> Based on the results from the perf testing (see below), this change
>> has no performance impact.
>>
>> Webrev:
>> http://cr.openjdk.java.net/~ehelin/8034852/webrev.00/
>>
>> Testing:
>> - JPRT
>> - Ad-hoc testing:
>>   - Kitchensink
>>   - Dacapo
>>   - Medrec
>>   - runThese
>>   - Parallel Class Loading testlist
>>   - Metaspace testlist
>>   - GC nightly testlist
>> - Perf testing:
>>   - SPECjbb2005
>>   - SPECjbb2013
>>   - Derby
>> - Derby regression tests
>>
>> Thanks,
>> Erik
>


More information about the hotspot-dev mailing list