RFR(S) 8245925 G1 allocates EDEN region after CDS has executed GC
Ioi Lam
ioi.lam at oracle.com
Thu Jun 4 18:36:54 UTC 2020
On 6/4/20 11:02 AM, Yumin Qi wrote:
> Hi, Ioi
>
> Glad you make it simple.
>
> metaspaceShared.cpp:
>
> 1612 void VM_PopulateDumpSharedSpace::doit() {
> 1613 if (HeapShared::is_heap_object_archiving_allowed()) {
> 1614 // Avoid fragmentation while archiving heap objects.
> 1615 if (GCLocker::is_active()) {
> 1616 // This should rarely happen during -Xshare:dump, if at all, but
> just to be safe.
> 1617 log_debug(cds)("GCLocker::is_active() ... try again");
> 1618 return;
> 1619 }
> 1620
> 1621 log_debug(cds)("Run GC ...");
> 1622 Universe::heap()->collect_as_vm_thread(GCCause::_archive_time_gc);
> 1623 log_debug(cds)("Run GC done");
> 1624 }
>
> I think the check for GCLocker should be after the collection, the G1
> full collection will check active GC:
>
> bool G1CollectedHeap::do_full_collection(bool explicit_gc, bool
> clear_all_soft_refs) {
> assert_at_safepoint_on_vm_thread();
> if (GCLocker::check_active_before_gc()) {
> // Full GC was not completed. return false;
> }
>
> It should be very rare for dumping that full collection aborted
> premature, but put the checking after collection seems safer.
>
>
I copied the code from here (src/hotspot/share/services/heapDumper.cpp)
void VM_HeapDumper::doit() {
CollectedHeap* ch = Universe::heap();
ch->ensure_parsability(false); // must happen, even if collection does
// not happen (e.g. due to GCLocker)
if (_gc_before_heap_dump) {
if (GCLocker::is_active()) {
warning("GC locker is held; pre-heapdump GC was skipped");
} else {
ch->collect_as_vm_thread(GCCause::_heap_dump);
}
}
Could someone on the GC team comment whether this is the correct way to
do it?
(I should probably add ensure_parsability() to my code as well??).
> For test GCDuringDump.java:
>
> 64 String extraArg = (i == 0) ? "-showversion" : "-javaagent:" + agentJar;
> 65 String extraOption = (i == 0) ? "-showversion" :
> "-XX:+AllowArchivingWithJavaAgent";
> 66 String extraOption2 = (i != 2) ? "-showversion" :
> "-Dtest.with.cleaner=true";
>
> Is that correct for line 65? for i = 0, both extraArg and extraOption
> will be same, looks a bug.
"-showversion" is just a way to pass a "no-op" to TestCommon.testDump.
It's a harmless option and can be repeated several times.
Thanks
- Ioi
>
> Others looks OK to me. Thanks Yumin
>
> On 6/3/20 10:53 PM, Ioi Lam wrote:
>>
>>> On 5/29/20 9:40 PM, Yumin Qi wrote:
>>>> HI, Ioi
>>>>
>>>> If the allocation of EDEN happens between GC and dump, should we
>>>> put the GC action in VM_PopulateDumpSharedSpace? This way, at
>>>> safepoint there should no allocation happens. The stack trace
>>>> showed it happened with a Java Thread, which should be blocked at
>>>> safepoint.
>>>>
>>>
>>> Hi Yumin,
>>>
>>> I think GCs cannot be executed inside a safepoint, because some
>>> parts of GC need to execute in a safepoint, so they will be blocked
>>> until VM_PopulateDumpSharedSpace::doit has returned.
>>>
>>> Anyway, as I mentioned in my reply to Jiangli, there's a better way
>>> to fix this, so I will withdraw the current patch.
>>>
>>
>> Hi Yumin,
>>
>> Actually, I changed my mind again, and implemented your suggestion :-)
>>
>> There's actually a way to invoke GC inside a safepoint (it's used by
>> "jcmd gc.heap_dump", for example). So I changed the CDS code to do
>> the same thing. It's a much simpler change and does what I want -- no
>> other thread will be able to make any heap allocation after the GC
>> has completed, so no EDEN region will be allocated:
>>
>> http://cr.openjdk.java.net/~iklam/jdk15/8245925-g1-eden-after-cds-gc.v02/
>>
>>
>> The check for "if (GCLocker::is_active())" should almost always be
>> false. I left it there just for safety:
>>
>> During -Xshare:dump, we execute Java code to build the module graph,
>> load classes, etc. So theoretically someone could try to parallelize
>> some of that Java code in the future. Theoretically when CDS has
>> entered the safepoint, another thread could be in the middle a JNI
>> method that has held the GCLock.
>>
>> Thanks
>> - Ioi
>>
>>>
>>>>
>>>> On 5/29/20 7:29 PM, Ioi Lam wrote:
>>>>> https://bugs.openjdk.java.net/browse/JDK-8245925
>>>>> http://cr.openjdk.java.net/~iklam/jdk15/8245925-g1-eden-after-cds-gc.v01/
>>>>>
>>>>>
>>>>>
>>>>> Summary:
>>>>>
>>>>> CDS supports archived heap objects only for G1. During -Xshare:dump,
>>>>> CDS executes a full GC so that G1 will compact the heap regions,
>>>>> leaving
>>>>> maximum contiguous free space at the top of the heap. Then, the
>>>>> archived
>>>>> heap regions are allocated from the top of the heap.
>>>>>
>>>>> Under some circumstances, java.lang.ref.Cleaners will execute
>>>>> after the GC has completed. The cleaners may allocate or
>>>>> synchronized, which
>>>>> will cause G1 to allocate an EDEN region at the top of the heap.
>>>>>
>>>>> The fix is simple -- after CDS has entered a safepoint, if EDEN
>>>>> regions exist,
>>>>> exit the safepoint, run GC, and try again. Eventually all the
>>>>> cleaners will
>>>>> be executed and no more allocation can happen.
>>>>>
>>>>> For safety, I limit the retry count to 30 (or about total 9 seconds).
>>>>>
>>>>> Thanks
>>>>> - Ioi
>>>>>
>>>>>
>>>>> <https://bugs.openjdk.java.net/browse/JDK-8245925>
>>>>
>>>
>>
>
More information about the hotspot-gc-dev
mailing list