< prev index next >
src/hotspot/share/memory/metaspace.cpp
Print this page
*** 21,33 ****
* questions.
*
*/
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
#include "gc/shared/collectedHeap.hpp"
! #include "gc/shared/collectorPolicy.hpp"
! #include "gc/shared/gcLocker.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.hpp"
#include "memory/binaryTreeDictionary.hpp"
#include "memory/filemap.hpp"
--- 21,34 ----
* questions.
*
*/
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
+ #include "classfile/classLoaderData.hpp"
#include "gc/shared/collectedHeap.hpp"
! #include "gc/shared/gcLocker.inline.hpp"
! #include "gc/shared/vmGCOperations.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.hpp"
#include "memory/binaryTreeDictionary.hpp"
#include "memory/filemap.hpp"
*** 43,52 ****
--- 44,54 ----
#include "runtime/globals.hpp"
#include "runtime/init.hpp"
#include "runtime/java.hpp"
#include "runtime/mutex.hpp"
#include "runtime/orderAccess.inline.hpp"
+ #include "runtime/vmThread.hpp"
#include "services/memTracker.hpp"
#include "services/memoryService.hpp"
#include "utilities/align.hpp"
#include "utilities/copy.hpp"
#include "utilities/debug.hpp"
*** 1819,1828 ****
--- 1821,1904 ----
new_capacity_until_GC,
MetaspaceGCThresholdUpdater::ComputeNewSize);
}
}
+ MetaWord* MetaspaceGC::satisfy_failed_metadata_allocation(ClassLoaderData* loader_data,
+ size_t word_size,
+ Metaspace::MetadataType mdtype) {
+ uint loop_count = 0;
+ uint gc_count = 0;
+ uint full_gc_count = 0;
+
+ assert(!Heap_lock->owned_by_self(), "Should not be holding the Heap_lock");
+
+ do {
+ MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype);
+ if (result != NULL) {
+ return result;
+ }
+
+ if (GCLocker::is_active_and_needs_gc()) {
+ // If the GCLocker is active, just expand and allocate.
+ // If that does not succeed, wait if this thread is not
+ // in a critical section itself.
+ result = loader_data->metaspace_non_null()->expand_and_allocate(word_size, mdtype);
+ if (result != NULL) {
+ return result;
+ }
+ JavaThread* jthr = JavaThread::current();
+ if (!jthr->in_critical()) {
+ // Wait for JNI critical section to be exited
+ GCLocker::stall_until_clear();
+ // The GC invoked by the last thread leaving the critical
+ // section will be a young collection and a full collection
+ // is (currently) needed for unloading classes so continue
+ // to the next iteration to get a full GC.
+ continue;
+ } else {
+ if (CheckJNICalls) {
+ fatal("Possible deadlock due to allocating while"
+ " in jni critical section");
+ }
+ return NULL;
+ }
+ }
+
+ { // Need lock to get self consistent gc_count's
+ MutexLocker ml(Heap_lock);
+ gc_count = Universe::heap()->total_collections();
+ full_gc_count = Universe::heap()->total_full_collections();
+ }
+
+ // Generate a VM operation
+ VM_CollectForMetadataAllocation op(loader_data,
+ word_size,
+ mdtype,
+ gc_count,
+ full_gc_count,
+ GCCause::_metadata_GC_threshold);
+ VMThread::execute(&op);
+
+ // If GC was locked out, try again. Check before checking success because the
+ // prologue could have succeeded and the GC still have been locked out.
+ if (op.gc_locked()) {
+ continue;
+ }
+
+ if (op.prologue_succeeded()) {
+ return op.result();
+ }
+ loop_count++;
+ if ((QueuedAllocationWarningCount > 0) &&
+ (loop_count % QueuedAllocationWarningCount == 0)) {
+ log_warning(gc, ergo)("satisfy_failed_metadata_allocation() retries %d times,"
+ " size=" SIZE_FORMAT, loop_count, word_size);
+ }
+ } while (true); // Until a GC is done
+ }
+
// Metadebug methods
void Metadebug::init_allocation_fail_alot_count() {
if (MetadataAllocationFailALot) {
_allocation_fail_alot_count =
*** 3950,3961 ****
// Allocation failed.
if (is_init_completed()) {
// Only start a GC if the bootstrapping has completed.
// Try to clean out some memory and retry.
! result = Universe::heap()->collector_policy()->satisfy_failed_metadata_allocation(
! loader_data, word_size, mdtype);
}
}
if (result == NULL) {
SpaceManager* sm;
--- 4026,4036 ----
// Allocation failed.
if (is_init_completed()) {
// Only start a GC if the bootstrapping has completed.
// Try to clean out some memory and retry.
! result = Universe::heap()->satisfy_failed_metadata_allocation(loader_data, word_size, mdtype);
}
}
if (result == NULL) {
SpaceManager* sm;
< prev index next >