mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8319313: G1: Rename G1EvacFailureInjector appropriately
Reviewed-by: mli, iwalulya, ayang
This commit is contained in:
parent
a7f6016406
commit
86f9b3f52a
@ -70,7 +70,7 @@
|
||||
#include "gc/g1/g1UncommitRegionTask.hpp"
|
||||
#include "gc/g1/g1VMOperations.hpp"
|
||||
#include "gc/g1/g1YoungCollector.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
#include "gc/g1/heapRegion.inline.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.inline.hpp"
|
||||
#include "gc/g1/heapRegionSet.inline.hpp"
|
||||
@ -1144,7 +1144,7 @@ G1CollectedHeap::G1CollectedHeap() :
|
||||
_numa(G1NUMA::create()),
|
||||
_hrm(),
|
||||
_allocator(nullptr),
|
||||
_evac_failure_injector(),
|
||||
_allocation_failure_injector(),
|
||||
_verifier(nullptr),
|
||||
_summary_bytes_used(0),
|
||||
_bytes_used_during_gc(0),
|
||||
@ -1432,7 +1432,7 @@ jint G1CollectedHeap::initialize() {
|
||||
|
||||
_collection_set.initialize(max_reserved_regions());
|
||||
|
||||
evac_failure_injector()->reset();
|
||||
allocation_failure_injector()->reset();
|
||||
|
||||
CPUTimeCounters::create_counter(CPUTimeGroups::CPUTimeType::gc_parallel_workers);
|
||||
CPUTimeCounters::create_counter(CPUTimeGroups::CPUTimeType::gc_conc_mark);
|
||||
@ -3002,9 +3002,6 @@ void G1CollectedHeap::unregister_nmethod(nmethod* nm) {
|
||||
|
||||
void G1CollectedHeap::update_used_after_gc(bool evacuation_failed) {
|
||||
if (evacuation_failed) {
|
||||
// Reset the G1EvacuationFailureALot counters and flags
|
||||
evac_failure_injector()->reset();
|
||||
|
||||
set_used(recalculate_used());
|
||||
} else {
|
||||
// The "used" of the collection set have already been subtracted
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
#include "gc/g1/g1MonotonicArenaFreePool.hpp"
|
||||
#include "gc/g1/g1NUMA.hpp"
|
||||
#include "gc/g1/g1SurvivorRegions.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
#include "gc/g1/heapRegionSet.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
@ -220,7 +220,7 @@ private:
|
||||
// Manages all allocations with regions except humongous object allocations.
|
||||
G1Allocator* _allocator;
|
||||
|
||||
G1YoungGCEvacFailureInjector _evac_failure_injector;
|
||||
G1YoungGCAllocationFailureInjector _allocation_failure_injector;
|
||||
|
||||
// Manages all heap verification.
|
||||
G1HeapVerifier* _verifier;
|
||||
@ -550,7 +550,7 @@ public:
|
||||
return _allocator;
|
||||
}
|
||||
|
||||
G1YoungGCEvacFailureInjector* evac_failure_injector() { return &_evac_failure_injector; }
|
||||
G1YoungGCAllocationFailureInjector* allocation_failure_injector() { return &_allocation_failure_injector; }
|
||||
|
||||
G1HeapVerifier* verifier() {
|
||||
return _verifier;
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
#include "gc/g1/g1RootClosures.hpp"
|
||||
#include "gc/g1/g1StringDedup.hpp"
|
||||
#include "gc/g1/g1Trace.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.inline.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp"
|
||||
#include "gc/shared/continuationGCSupport.inline.hpp"
|
||||
#include "gc/shared/partialArrayTaskStepper.inline.hpp"
|
||||
#include "gc/shared/preservedMarks.inline.hpp"
|
||||
@ -85,7 +85,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
|
||||
_max_num_optional_regions(collection_set->optional_region_length()),
|
||||
_numa(g1h->numa()),
|
||||
_obj_alloc_stat(nullptr),
|
||||
EVAC_FAILURE_INJECTOR_ONLY(_evac_failure_inject_counter(0) COMMA)
|
||||
ALLOCATION_FAILURE_INJECTOR_ONLY(_allocation_failure_inject_counter(0) COMMA)
|
||||
_preserved_marks(preserved_marks),
|
||||
_evacuation_failed_info(),
|
||||
_evac_failure_regions(evac_failure_regions),
|
||||
@ -427,9 +427,9 @@ HeapWord* G1ParScanThreadState::allocate_copy_slow(G1HeapRegionAttr* dest_attr,
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
bool G1ParScanThreadState::inject_allocation_failure(uint region_idx) {
|
||||
return _g1h->evac_failure_injector()->evacuation_should_fail(_evac_failure_inject_counter, region_idx);
|
||||
return _g1h->allocation_failure_injector()->allocation_should_fail(_allocation_failure_inject_counter, region_idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/g1/g1RedirtyCardsQueue.hpp"
|
||||
#include "gc/g1/g1OopClosures.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
#include "gc/shared/ageTable.hpp"
|
||||
#include "gc/shared/copyFailedInfo.hpp"
|
||||
@ -104,7 +104,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
|
||||
size_t* _obj_alloc_stat;
|
||||
|
||||
// Per-thread evacuation failure data structures.
|
||||
EVAC_FAILURE_INJECTOR_ONLY(size_t _evac_failure_inject_counter;)
|
||||
ALLOCATION_FAILURE_INJECTOR_ONLY(size_t _allocation_failure_inject_counter;)
|
||||
|
||||
PreservedMarks* _preserved_marks;
|
||||
EvacuationFailedInfo _evacuation_failed_info;
|
||||
@ -120,7 +120,7 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
|
||||
// Enqueue the card of p into the (evacuation failed) region.
|
||||
template <class T> void enqueue_card_into_evac_fail_region(T* p, oop obj);
|
||||
|
||||
bool inject_allocation_failure(uint region_idx) EVAC_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
bool inject_allocation_failure(uint region_idx) ALLOCATION_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
|
||||
public:
|
||||
G1ParScanThreadState(G1CollectedHeap* g1h,
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
#include "gc/g1/g1CollectorState.hpp"
|
||||
#include "gc/g1/g1ConcurrentMark.hpp"
|
||||
#include "gc/g1/g1GCPhaseTimes.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1EvacFailureRegions.inline.hpp"
|
||||
#include "gc/g1/g1EvacInfo.hpp"
|
||||
#include "gc/g1/g1HRPrinter.hpp"
|
||||
@ -46,6 +45,7 @@
|
||||
#include "gc/g1/g1RootProcessor.hpp"
|
||||
#include "gc/g1/g1Trace.hpp"
|
||||
#include "gc/g1/g1YoungCollector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCPostEvacuateTasks.hpp"
|
||||
#include "gc/g1/g1YoungGCPreEvacuateTasks.hpp"
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
@ -243,8 +243,8 @@ WorkerThreads* G1YoungCollector::workers() const {
|
||||
return _g1h->workers();
|
||||
}
|
||||
|
||||
G1YoungGCEvacFailureInjector* G1YoungCollector::evac_failure_injector() const {
|
||||
return _g1h->evac_failure_injector();
|
||||
G1YoungGCAllocationFailureInjector* G1YoungCollector::allocation_failure_injector() const {
|
||||
return _g1h->allocation_failure_injector();
|
||||
}
|
||||
|
||||
|
||||
@ -534,7 +534,7 @@ void G1YoungCollector::pre_evacuate_collection_set(G1EvacInfo* evacuation_info)
|
||||
DerivedPointerTable::clear();
|
||||
#endif
|
||||
|
||||
evac_failure_injector()->arm_if_needed();
|
||||
allocation_failure_injector()->arm_if_needed();
|
||||
}
|
||||
|
||||
class G1ParEvacuateFollowersClosure : public VoidClosure {
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
#define SHARE_GC_G1_G1YOUNGCOLLECTOR_HPP
|
||||
|
||||
#include "gc/g1/g1EvacFailureRegions.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
#include "gc/shared/gcCause.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
|
||||
@ -49,7 +49,7 @@ class G1Policy;
|
||||
class G1RedirtyCardsQueueSet;
|
||||
class G1RemSet;
|
||||
class G1SurvivorRegions;
|
||||
class G1YoungGCEvacFailureInjector;
|
||||
class G1YoungGCAllocationFailureInjector;
|
||||
class STWGCTimer;
|
||||
class WorkerThreads;
|
||||
|
||||
@ -78,7 +78,7 @@ class G1YoungCollector {
|
||||
G1SurvivorRegions* survivor_regions() const;
|
||||
ReferenceProcessor* ref_processor_stw() const;
|
||||
WorkerThreads* workers() const;
|
||||
G1YoungGCEvacFailureInjector* evac_failure_injector() const;
|
||||
G1YoungGCAllocationFailureInjector* allocation_failure_injector() const;
|
||||
|
||||
GCCause::Cause _gc_cause;
|
||||
|
||||
|
||||
114
src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp
Normal file
114
src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp"
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
|
||||
class SelectAllocationFailureRegionClosure : public HeapRegionClosure {
|
||||
CHeapBitMap& _allocation_failure_regions;
|
||||
size_t _allocation_failure_regions_num;
|
||||
|
||||
public:
|
||||
SelectAllocationFailureRegionClosure(CHeapBitMap& allocation_failure_regions, size_t cset_length) :
|
||||
_allocation_failure_regions(allocation_failure_regions),
|
||||
_allocation_failure_regions_num(cset_length * G1GCAllocationFailureALotCSetPercent / 100) { }
|
||||
|
||||
bool do_heap_region(HeapRegion* r) override {
|
||||
assert(r->in_collection_set(), "must be");
|
||||
if (_allocation_failure_regions_num > 0) {
|
||||
_allocation_failure_regions.set_bit(r->hrm_index());
|
||||
--_allocation_failure_regions_num;
|
||||
}
|
||||
return _allocation_failure_regions_num == 0;
|
||||
}
|
||||
};
|
||||
|
||||
G1YoungGCAllocationFailureInjector::G1YoungGCAllocationFailureInjector()
|
||||
: _inject_allocation_failure_for_current_gc(),
|
||||
_last_collection_with_allocation_failure(),
|
||||
_allocation_failure_regions(mtGC) {}
|
||||
|
||||
void G1YoungGCAllocationFailureInjector::select_allocation_failure_regions() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
_allocation_failure_regions.reinitialize(g1h->max_reserved_regions());
|
||||
SelectAllocationFailureRegionClosure closure(_allocation_failure_regions, g1h->collection_set()->cur_length());
|
||||
g1h->collection_set_iterate_all(&closure);
|
||||
}
|
||||
|
||||
bool G1YoungGCAllocationFailureInjector::arm_if_needed_for_gc_type(bool for_young_only_phase,
|
||||
bool during_concurrent_start,
|
||||
bool mark_or_rebuild_in_progress) {
|
||||
bool res = false;
|
||||
if (mark_or_rebuild_in_progress) {
|
||||
res |= G1GCAllocationFailureALotDuringConcMark;
|
||||
}
|
||||
if (during_concurrent_start) {
|
||||
res |= G1GCAllocationFailureALotDuringConcurrentStart;
|
||||
}
|
||||
if (for_young_only_phase) {
|
||||
res |= G1GCAllocationFailureALotDuringYoungGC;
|
||||
} else {
|
||||
// GCs are mixed
|
||||
res |= G1GCAllocationFailureALotDuringMixedGC;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void G1YoungGCAllocationFailureInjector::arm_if_needed() {
|
||||
if (G1GCAllocationFailureALot) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
// Check if we have gone over the interval.
|
||||
const size_t gc_num = g1h->total_collections();
|
||||
const size_t elapsed_gcs = gc_num - _last_collection_with_allocation_failure;
|
||||
|
||||
_inject_allocation_failure_for_current_gc = (elapsed_gcs >= G1GCAllocationFailureALotInterval);
|
||||
|
||||
// Now check if evacuation failure injection should be enabled for the current GC.
|
||||
G1CollectorState* collector_state = g1h->collector_state();
|
||||
const bool in_young_only_phase = collector_state->in_young_only_phase();
|
||||
const bool in_concurrent_start_gc = collector_state->in_concurrent_start_gc();
|
||||
const bool mark_or_rebuild_in_progress = collector_state->mark_or_rebuild_in_progress();
|
||||
|
||||
_inject_allocation_failure_for_current_gc &=
|
||||
arm_if_needed_for_gc_type(in_young_only_phase,
|
||||
in_concurrent_start_gc,
|
||||
mark_or_rebuild_in_progress);
|
||||
|
||||
if (_inject_allocation_failure_for_current_gc) {
|
||||
select_allocation_failure_regions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G1YoungGCAllocationFailureInjector::reset() {
|
||||
_last_collection_with_allocation_failure = G1CollectedHeap::heap()->total_collections();
|
||||
_inject_allocation_failure_for_current_gc = false;
|
||||
}
|
||||
|
||||
#endif // #if ALLOCATION_FAILURE_INJECTOR
|
||||
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_HPP
|
||||
#define SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_HPP
|
||||
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
#include "memory/allStatic.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
#define ALLOCATION_FAILURE_INJECTOR_RETURN
|
||||
#define ALLOCATION_FAILURE_INJECTOR_RETURN_(code)
|
||||
#define ALLOCATION_FAILURE_INJECTOR_ONLY(code) code
|
||||
#else
|
||||
#define ALLOCATION_FAILURE_INJECTOR_RETURN { return; }
|
||||
#define ALLOCATION_FAILURE_INJECTOR_RETURN_(code) { code }
|
||||
#define ALLOCATION_FAILURE_INJECTOR_ONLY(code)
|
||||
#endif // ALLOCATION_FAILURE_INJECTOR
|
||||
|
||||
// Support for injecting allocation failures based on the G1GCAllocationFailureALot*
|
||||
// flags. Analogous to PromotionFailureALot for the other collectors.
|
||||
//
|
||||
// Every G1GCAllocationFailureALotInterval collections without evacuation failure
|
||||
// in between we "arm" the injector to induce allocation failures after
|
||||
// G1GCAllocationFailureALotCount successful evacuations.
|
||||
//
|
||||
// Available only when ALLOCATION_FAILURE_INJECTOR is defined.
|
||||
class G1YoungGCAllocationFailureInjector {
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
// Should we inject evacuation failures in the current GC.
|
||||
bool _inject_allocation_failure_for_current_gc;
|
||||
|
||||
// Records the number of the last collection when allocation failure happened.
|
||||
// Used to determine whether allocation failure injection should be in effect
|
||||
// for the current GC.
|
||||
size_t _last_collection_with_allocation_failure;
|
||||
|
||||
// Records the regions that will fail evacuation.
|
||||
CHeapBitMap _allocation_failure_regions;
|
||||
#endif
|
||||
|
||||
bool arm_if_needed_for_gc_type(bool for_young_only_phase,
|
||||
bool during_concurrent_start,
|
||||
bool mark_or_rebuild_in_progress) ALLOCATION_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
|
||||
// Selects the regions that will fail allocation by G1GCAllocationFailureALotCSetPercent.
|
||||
void select_allocation_failure_regions() ALLOCATION_FAILURE_INJECTOR_RETURN;
|
||||
public:
|
||||
|
||||
G1YoungGCAllocationFailureInjector() ALLOCATION_FAILURE_INJECTOR_RETURN;
|
||||
|
||||
// Arm the allocation failure injector if needed for the current
|
||||
// GC (based upon the type of GC and which command line flags are set);
|
||||
void arm_if_needed() ALLOCATION_FAILURE_INJECTOR_RETURN;
|
||||
|
||||
// Return true if it's time to cause an allocation failure; the caller
|
||||
// provides the (preferably thread-local) counter to minimize performance impact.
|
||||
bool allocation_should_fail(size_t& counter, uint region_idx) ALLOCATION_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
|
||||
// Reset the allocation failure injection counters. Should be called at
|
||||
// the end of an evacuation pause in which an allocation failure occurred.
|
||||
void reset() ALLOCATION_FAILURE_INJECTOR_RETURN;
|
||||
};
|
||||
|
||||
#endif /* SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_HPP */
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,30 +22,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_INLINE_HPP
|
||||
#define SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_INLINE_HPP
|
||||
#ifndef SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_INLINE_HPP
|
||||
#define SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_INLINE_HPP
|
||||
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/g1YoungGCAllocationFailureInjector.hpp"
|
||||
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
|
||||
inline bool G1YoungGCEvacFailureInjector::evacuation_should_fail(size_t& counter, uint region_idx) {
|
||||
if (!_inject_evacuation_failure_for_current_gc) {
|
||||
inline bool G1YoungGCAllocationFailureInjector::allocation_should_fail(size_t& counter, uint region_idx) {
|
||||
if (!_inject_allocation_failure_for_current_gc) {
|
||||
return false;
|
||||
}
|
||||
if (!_evac_failure_regions.at(region_idx)) {
|
||||
if (!_allocation_failure_regions.at(region_idx)) {
|
||||
return false;
|
||||
}
|
||||
if (++counter < G1EvacuationFailureALotCount) {
|
||||
if (++counter < G1GCAllocationFailureALotCount) {
|
||||
return false;
|
||||
}
|
||||
counter = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // #if EVAC_FAILURE_INJECTOR
|
||||
#endif // #if ALLOCATION_FAILURE_INJECTOR
|
||||
|
||||
#endif /* SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_INLINE_HPP */
|
||||
#endif /* SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_INLINE_HPP */
|
||||
@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.inline.hpp"
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
|
||||
class SelectEvacFailureRegionClosure : public HeapRegionClosure {
|
||||
CHeapBitMap& _evac_failure_regions;
|
||||
size_t _evac_failure_regions_num;
|
||||
|
||||
public:
|
||||
SelectEvacFailureRegionClosure(CHeapBitMap& evac_failure_regions, size_t cset_length) :
|
||||
_evac_failure_regions(evac_failure_regions),
|
||||
_evac_failure_regions_num(cset_length * G1EvacuationFailureALotCSetPercent / 100) { }
|
||||
|
||||
bool do_heap_region(HeapRegion* r) override {
|
||||
assert(r->in_collection_set(), "must be");
|
||||
if (_evac_failure_regions_num > 0) {
|
||||
_evac_failure_regions.set_bit(r->hrm_index());
|
||||
--_evac_failure_regions_num;
|
||||
}
|
||||
return _evac_failure_regions_num == 0;
|
||||
}
|
||||
};
|
||||
|
||||
G1YoungGCEvacFailureInjector::G1YoungGCEvacFailureInjector()
|
||||
: _inject_evacuation_failure_for_current_gc(),
|
||||
_last_collection_with_evacuation_failure(),
|
||||
_evac_failure_regions(mtGC) {}
|
||||
|
||||
void G1YoungGCEvacFailureInjector::select_evac_failure_regions() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
_evac_failure_regions.reinitialize(g1h->max_reserved_regions());
|
||||
SelectEvacFailureRegionClosure closure(_evac_failure_regions, g1h->collection_set()->cur_length());
|
||||
g1h->collection_set_iterate_all(&closure);
|
||||
}
|
||||
|
||||
bool G1YoungGCEvacFailureInjector::arm_if_needed_for_gc_type(bool for_young_only_phase,
|
||||
bool during_concurrent_start,
|
||||
bool mark_or_rebuild_in_progress) {
|
||||
bool res = false;
|
||||
if (mark_or_rebuild_in_progress) {
|
||||
res |= G1EvacuationFailureALotDuringConcMark;
|
||||
}
|
||||
if (during_concurrent_start) {
|
||||
res |= G1EvacuationFailureALotDuringConcurrentStart;
|
||||
}
|
||||
if (for_young_only_phase) {
|
||||
res |= G1EvacuationFailureALotDuringYoungGC;
|
||||
} else {
|
||||
// GCs are mixed
|
||||
res |= G1EvacuationFailureALotDuringMixedGC;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void G1YoungGCEvacFailureInjector::arm_if_needed() {
|
||||
if (G1EvacuationFailureALot) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
// Check if we have gone over the interval.
|
||||
const size_t gc_num = g1h->total_collections();
|
||||
const size_t elapsed_gcs = gc_num - _last_collection_with_evacuation_failure;
|
||||
|
||||
_inject_evacuation_failure_for_current_gc = (elapsed_gcs >= G1EvacuationFailureALotInterval);
|
||||
|
||||
// Now check if evacuation failure injection should be enabled for the current GC.
|
||||
G1CollectorState* collector_state = g1h->collector_state();
|
||||
const bool in_young_only_phase = collector_state->in_young_only_phase();
|
||||
const bool in_concurrent_start_gc = collector_state->in_concurrent_start_gc();
|
||||
const bool mark_or_rebuild_in_progress = collector_state->mark_or_rebuild_in_progress();
|
||||
|
||||
_inject_evacuation_failure_for_current_gc &=
|
||||
arm_if_needed_for_gc_type(in_young_only_phase,
|
||||
in_concurrent_start_gc,
|
||||
mark_or_rebuild_in_progress);
|
||||
|
||||
if (_inject_evacuation_failure_for_current_gc) {
|
||||
select_evac_failure_regions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G1YoungGCEvacFailureInjector::reset() {
|
||||
_last_collection_with_evacuation_failure = G1CollectedHeap::heap()->total_collections();
|
||||
_inject_evacuation_failure_for_current_gc = false;
|
||||
}
|
||||
|
||||
#endif // #if EVAC_FAILURE_INJECTOR
|
||||
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_HPP
|
||||
#define SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_HPP
|
||||
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
#include "memory/allStatic.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
#define EVAC_FAILURE_INJECTOR_RETURN
|
||||
#define EVAC_FAILURE_INJECTOR_RETURN_(code)
|
||||
#define EVAC_FAILURE_INJECTOR_ONLY(code) code
|
||||
#else
|
||||
#define EVAC_FAILURE_INJECTOR_RETURN { return; }
|
||||
#define EVAC_FAILURE_INJECTOR_RETURN_(code) { code }
|
||||
#define EVAC_FAILURE_INJECTOR_ONLY(code)
|
||||
#endif // EVAC_FAILURE_INJECTOR
|
||||
|
||||
// Support for injecting evacuation failures based on the G1EvacuationFailureALot*
|
||||
// flags. Analogous to PromotionFailureALot for the other collectors.
|
||||
//
|
||||
// Every G1EvacuationFailureALotInterval collections without evacuation failure
|
||||
// in between we "arm" the injector to induce evacuation failures after
|
||||
// G1EvacuationFailureALotCount successful evacuations.
|
||||
//
|
||||
// Available only when EVAC_FAILURE_INJECTOR is defined.
|
||||
class G1YoungGCEvacFailureInjector {
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
// Should we inject evacuation failures in the current GC.
|
||||
bool _inject_evacuation_failure_for_current_gc;
|
||||
|
||||
// Records the number of the last collection when evacuation failure happened.
|
||||
// Used to determine whether evacuation failure injection should be in effect
|
||||
// for the current GC.
|
||||
size_t _last_collection_with_evacuation_failure;
|
||||
|
||||
// Records the regions that will fail evacuation.
|
||||
CHeapBitMap _evac_failure_regions;
|
||||
#endif
|
||||
|
||||
bool arm_if_needed_for_gc_type(bool for_young_only_phase,
|
||||
bool during_concurrent_start,
|
||||
bool mark_or_rebuild_in_progress) EVAC_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
|
||||
// Selects the regions that will fail evacuation by G1EvacuationFailureALotCSetPercent.
|
||||
void select_evac_failure_regions() EVAC_FAILURE_INJECTOR_RETURN;
|
||||
public:
|
||||
|
||||
G1YoungGCEvacFailureInjector() EVAC_FAILURE_INJECTOR_RETURN;
|
||||
|
||||
// Arm the evacuation failure injector if needed for the current
|
||||
// GC (based upon the type of GC and which command line flags are set);
|
||||
void arm_if_needed() EVAC_FAILURE_INJECTOR_RETURN;
|
||||
|
||||
// Return true if it's time to cause an evacuation failure; the caller
|
||||
// provides the (preferably thread-local) counter to minimize performance impact.
|
||||
bool evacuation_should_fail(size_t& counter, uint region_idx) EVAC_FAILURE_INJECTOR_RETURN_( return false; );
|
||||
|
||||
// Reset the evacuation failure injection counters. Should be called at
|
||||
// the end of an evacuation pause in which an evacuation failure occurred.
|
||||
void reset() EVAC_FAILURE_INJECTOR_RETURN;
|
||||
};
|
||||
|
||||
#endif /* SHARE_GC_G1_G1YOUNGGCEVACUATIONFAILUREINJECTOR_HPP */
|
||||
@ -67,16 +67,26 @@ public:
|
||||
|
||||
class G1PostEvacuateCollectionSetCleanupTask1::RecalculateUsedTask : public G1AbstractSubTask {
|
||||
bool _evacuation_failed;
|
||||
bool _allocation_failed;
|
||||
|
||||
public:
|
||||
RecalculateUsedTask(bool evacuation_failed) : G1AbstractSubTask(G1GCPhaseTimes::RecalculateUsed), _evacuation_failed(evacuation_failed) { }
|
||||
RecalculateUsedTask(bool evacuation_failed, bool allocation_failed) :
|
||||
G1AbstractSubTask(G1GCPhaseTimes::RecalculateUsed),
|
||||
_evacuation_failed(evacuation_failed),
|
||||
_allocation_failed(allocation_failed) { }
|
||||
|
||||
double worker_cost() const override {
|
||||
// If there is no evacuation failure, the work to perform is minimal.
|
||||
return _evacuation_failed ? 1.0 : AlmostNoWork;
|
||||
}
|
||||
|
||||
void do_work(uint worker_id) override { G1CollectedHeap::heap()->update_used_after_gc(_evacuation_failed); }
|
||||
void do_work(uint worker_id) override {
|
||||
G1CollectedHeap::heap()->update_used_after_gc(_evacuation_failed);
|
||||
if (_allocation_failed) {
|
||||
// Reset the G1GCAllocationFailureALot counters and flags
|
||||
G1CollectedHeap::heap()->allocation_failure_injector()->reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class G1PostEvacuateCollectionSetCleanupTask1::SampleCollectionSetCandidatesTask : public G1AbstractSubTask {
|
||||
@ -309,9 +319,10 @@ G1PostEvacuateCollectionSetCleanupTask1::G1PostEvacuateCollectionSetCleanupTask1
|
||||
G1BatchedTask("Post Evacuate Cleanup 1", G1CollectedHeap::heap()->phase_times())
|
||||
{
|
||||
bool evac_failed = evac_failure_regions->has_regions_evac_failed();
|
||||
bool alloc_failed = evac_failure_regions->has_regions_alloc_failed();
|
||||
|
||||
add_serial_task(new MergePssTask(per_thread_states));
|
||||
add_serial_task(new RecalculateUsedTask(evac_failed));
|
||||
add_serial_task(new RecalculateUsedTask(evac_failed, alloc_failed));
|
||||
if (SampleCollectionSetCandidatesTask::should_execute()) {
|
||||
add_serial_task(new SampleCollectionSetCandidatesTask());
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,18 +27,18 @@
|
||||
|
||||
#include "runtime/globals_shared.hpp"
|
||||
|
||||
// Enable evacuation failure injector by default in non-product builds.
|
||||
// Enable allocation failure injector by default in non-product builds.
|
||||
|
||||
#ifdef EVAC_FAILURE_INJECTOR
|
||||
#error "EVAC_FAILURE_INJECTOR already defined"
|
||||
#ifdef ALLOCATION_FAILURE_INJECTOR
|
||||
#error "ALLOCATION_FAILURE_INJECTOR already defined"
|
||||
#endif
|
||||
#ifndef PRODUCT
|
||||
#define EVAC_FAILURE_INJECTOR 1
|
||||
#define ALLOCATION_FAILURE_INJECTOR 1
|
||||
#else
|
||||
#define EVAC_FAILURE_INJECTOR 0
|
||||
#define ALLOCATION_FAILURE_INJECTOR 0
|
||||
#endif
|
||||
|
||||
#if EVAC_FAILURE_INJECTOR
|
||||
#if ALLOCATION_FAILURE_INJECTOR
|
||||
#define GC_G1_EVACUATION_FAILURE_FLAGS(develop, \
|
||||
develop_pd, \
|
||||
product, \
|
||||
@ -47,38 +47,38 @@
|
||||
range, \
|
||||
constraint) \
|
||||
\
|
||||
product(bool, G1EvacuationFailureALot, false, \
|
||||
"Force use of evacuation failure handling during certain " \
|
||||
"evacuation pauses") \
|
||||
product(bool, G1GCAllocationFailureALot, false, \
|
||||
"Force execution of evacuation failure handling by inducing " \
|
||||
"allocation failures during certain young collection pauses") \
|
||||
\
|
||||
product(uintx, G1EvacuationFailureALotCount, 1000, \
|
||||
"Number of successful evacuations between evacuation failures " \
|
||||
"occurring at object copying per thread") \
|
||||
product(uintx, G1GCAllocationFailureALotCount, 1000, \
|
||||
"Number of successful evacuations between induced allocation " \
|
||||
"failures occurring at object copying per thread") \
|
||||
\
|
||||
product(uintx, G1EvacuationFailureALotInterval, 5, \
|
||||
product(uintx, G1GCAllocationFailureALotInterval, 5, \
|
||||
"Total collections between forced triggering of evacuation " \
|
||||
"failures") \
|
||||
\
|
||||
product(bool, G1EvacuationFailureALotDuringConcMark, true, \
|
||||
"Force use of evacuation failure handling during evacuation " \
|
||||
"pauses when marking is in progress") \
|
||||
product(bool, G1GCAllocationFailureALotDuringConcMark, true, \
|
||||
"Trigger evacuation failure handling in collection pauses where " \
|
||||
"marking is in progress") \
|
||||
\
|
||||
product(bool, G1EvacuationFailureALotDuringConcurrentStart, true, \
|
||||
"Force use of evacuation failure handling during concurrent " \
|
||||
"start evacuation pauses") \
|
||||
product(bool, G1GCAllocationFailureALotDuringConcurrentStart, true, \
|
||||
"Trigger evacuation failure handling during concurrent start " \
|
||||
"collection pauses") \
|
||||
\
|
||||
product(bool, G1EvacuationFailureALotDuringYoungGC, true, \
|
||||
"Force use of evacuation failure handling during young " \
|
||||
"evacuation pauses") \
|
||||
product(bool, G1GCAllocationFailureALotDuringYoungGC, true, \
|
||||
"Trigger evacuation failure handling during young collection " \
|
||||
"pauses") \
|
||||
\
|
||||
product(bool, G1EvacuationFailureALotDuringMixedGC, true, \
|
||||
product(bool, G1GCAllocationFailureALotDuringMixedGC, true, \
|
||||
"Force use of evacuation failure handling during mixed " \
|
||||
"evacuation pauses") \
|
||||
"collection pauses") \
|
||||
\
|
||||
product(uint, G1EvacuationFailureALotCSetPercent, 100, \
|
||||
product(uint, G1GCAllocationFailureALotCSetPercent, 100, \
|
||||
"The percentage of regions in the collection set starting " \
|
||||
"from the beginning where the forced evacuation failure " \
|
||||
"injection will be applied.") \
|
||||
"from the beginning where the allocation failures are " \
|
||||
"injected.") \
|
||||
range(1, 100)
|
||||
#else
|
||||
#define GC_G1_EVACUATION_FAILURE_FLAGS(develop, \
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
package gc.g1;
|
||||
|
||||
/*
|
||||
* @test TestEvacuationFailure
|
||||
* @test TestAllocationFailure
|
||||
* @summary Ensure the output for a minor GC with G1 that has allocation failure contains the correct strings.
|
||||
* @requires vm.gc.G1
|
||||
* @requires vm.debug
|
||||
@ -34,24 +34,24 @@ package gc.g1;
|
||||
* @build jdk.test.whitebox.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* gc.g1.TestEvacuationFailure
|
||||
* gc.g1.TestAllocationFailure
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class TestEvacuationFailure {
|
||||
public class TestAllocationFailure {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC",
|
||||
"-Xmx32M",
|
||||
"-Xmn16M",
|
||||
"-XX:+G1EvacuationFailureALot",
|
||||
"-XX:G1EvacuationFailureALotCount=100",
|
||||
"-XX:G1EvacuationFailureALotInterval=1",
|
||||
"-XX:+G1GCAllocationFailureALot",
|
||||
"-XX:G1GCAllocationFailureALotCount=100",
|
||||
"-XX:G1GCAllocationFailureALotInterval=1",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-Xlog:gc",
|
||||
GCTestWithEvacuationFailure.class.getName());
|
||||
GCTestWithAllocationFailure.class.getName());
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
System.out.println(output.getStdout());
|
||||
@ -59,17 +59,17 @@ public class TestEvacuationFailure {
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static class GCTestWithEvacuationFailure {
|
||||
static class GCTestWithAllocationFailure {
|
||||
private static byte[] garbage;
|
||||
private static byte[] largeObject;
|
||||
private static Object[] holder = new Object[200]; // Must be larger than G1EvacuationFailureALotCount
|
||||
private static Object[] holder = new Object[200]; // Must be larger than G1GCAllocationFailureALotCount
|
||||
|
||||
public static void main(String [] args) {
|
||||
largeObject = new byte[16 * 1024 * 1024];
|
||||
System.out.println("Creating garbage");
|
||||
// Create 16 MB of garbage. This should result in at least one GC,
|
||||
// (Heap size is 32M, we use 17MB for the large object above)
|
||||
// which is larger than G1EvacuationFailureALotInterval.
|
||||
// which is larger than G1GCAllocationFailureALotInterval.
|
||||
for (int i = 0; i < 16 * 1024; i++) {
|
||||
holder[i % holder.length] = new byte[1024];
|
||||
}
|
||||
@ -275,12 +275,12 @@ public class TestGCLogMessages {
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC",
|
||||
"-Xmx32M",
|
||||
"-Xmn16M",
|
||||
"-XX:+G1EvacuationFailureALot",
|
||||
"-XX:G1EvacuationFailureALotCount=100",
|
||||
"-XX:G1EvacuationFailureALotInterval=1",
|
||||
"-XX:+G1GCAllocationFailureALot",
|
||||
"-XX:G1GCAllocationFailureALotCount=100",
|
||||
"-XX:G1GCAllocationFailureALotInterval=1",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-Xlog:gc+phases=debug",
|
||||
GCTestWithEvacuationFailure.class.getName());
|
||||
GCTestWithAllocationFailure.class.getName());
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
checkMessagesAtLevel(output, exhFailureMessages, Level.DEBUG);
|
||||
@ -292,7 +292,7 @@ public class TestGCLogMessages {
|
||||
"-Xms32M",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-Xlog:gc+phases=trace",
|
||||
GCTestWithEvacuationFailure.class.getName());
|
||||
GCTestWithAllocationFailure.class.getName());
|
||||
|
||||
output = new OutputAnalyzer(pb.start());
|
||||
checkMessagesAtLevel(output, exhFailureMessages, Level.TRACE);
|
||||
@ -346,17 +346,17 @@ public class TestGCLogMessages {
|
||||
}
|
||||
}
|
||||
|
||||
static class GCTestWithEvacuationFailure {
|
||||
static class GCTestWithAllocationFailure {
|
||||
private static byte[] garbage;
|
||||
private static byte[] largeObject;
|
||||
private static Object[] holder = new Object[200]; // Must be larger than G1EvacuationFailureALotCount
|
||||
private static Object[] holder = new Object[200]; // Must be larger than G1GCAllocationFailureALotCount
|
||||
|
||||
public static void main(String [] args) {
|
||||
largeObject = new byte[16*1024*1024];
|
||||
System.out.println("Creating garbage");
|
||||
// Create 16 MB of garbage. This should result in at least one GC,
|
||||
// (Heap size is 32M, we use 17MB for the large object above)
|
||||
// which is larger than G1EvacuationFailureALotInterval.
|
||||
// which is larger than G1GCAllocationFailureALotInterval.
|
||||
for (int i = 0; i < 16 * 1024; i++) {
|
||||
holder[i % holder.length] = new byte[1024];
|
||||
}
|
||||
|
||||
@ -122,9 +122,9 @@ public class TestVerifyGCType {
|
||||
private static void testYoungEvacFail() throws Exception {
|
||||
OutputAnalyzer output;
|
||||
output = testWithVerificationType(new String[] {"young-evac-fail"},
|
||||
new String[] {"-XX:+G1EvacuationFailureALot",
|
||||
"-XX:G1EvacuationFailureALotCount=100",
|
||||
"-XX:G1EvacuationFailureALotInterval=1",
|
||||
new String[] {"-XX:+G1GCAllocationFailureALot",
|
||||
"-XX:G1GCAllocationFailureALotCount=100",
|
||||
"-XX:G1GCAllocationFailureALotInterval=1",
|
||||
"-XX:+UnlockDiagnosticVMOptions"});
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
|
||||
@ -47,8 +47,8 @@ import jdk.test.whitebox.WhiteBox;
|
||||
* @build jdk.test.whitebox.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* -Xmx32m -Xms32m -XX:+UnlockExperimentalVMOptions -XX:+G1EvacuationFailureALot
|
||||
* -XX:G1EvacuationFailureALotCount=100 -XX:G1EvacuationFailureALotInterval=1
|
||||
* -Xmx32m -Xms32m -XX:+UnlockExperimentalVMOptions -XX:+G1GCAllocationFailureALot
|
||||
* -XX:G1GCAllocationFailureALotCount=100 -XX:G1GCAllocationFailureALotInterval=1
|
||||
* -Xlog:gc=debug -XX:+UseG1GC jdk.jfr.event.gc.detailed.TestEvacuationFailedEvent
|
||||
*/
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user