--- old/src/share/vm/gc_implementation/shared/vmGCOperations.cpp 2014-02-07 17:50:16.554301208 +0100 +++ new/src/share/vm/gc_implementation/shared/vmGCOperations.cpp 2014-02-07 17:50:16.454301909 +0100 @@ -104,6 +104,14 @@ assert(((_gc_cause != GCCause::_no_gc) && (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); + // If a GC is initiated during startup and the the GC locker is locked, + // the VM initialization will fail because we are not yet ready to handle + // a GC. + if (GC_locker::fail_on_gc()) { + vm_exit_during_initialization( + err_msg("Too small young generation (" SIZE_FORMAT "K) to initialize VM.", NewSize / K)); + } + acquire_pending_list_lock(); // If the GC count has changed someone beat us to the collection // Get the Heap_lock after the pending_list_lock. --- old/src/share/vm/memory/gcLocker.hpp 2014-02-07 17:50:16.902298765 +0100 +++ new/src/share/vm/memory/gcLocker.hpp 2014-02-07 17:50:16.806299435 +0100 @@ -91,7 +91,8 @@ assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); return is_active_internal(); } - static bool needs_gc() { return _needs_gc; } + static bool needs_gc() { return _needs_gc; } + static bool fail_on_gc() { return _lock_count > 0; } // Shorthand static bool is_active_and_needs_gc() { --- old/src/share/vm/memory/metaspaceShared.cpp 2014-02-07 17:50:17.234296433 +0100 +++ new/src/share/vm/memory/metaspaceShared.cpp 2014-02-07 17:50:17.134297135 +0100 @@ -645,9 +645,6 @@ TraceTime timer("Dump Shared Spaces", TraceStartupTime); ResourceMark rm; - // Lock out GC - is it necessary? I don't think we care. - No_GC_Verifier no_gc; - // Preload classes to be shared. // Should use some os:: method rather than fopen() here. aB. // Construct the path to the class list (in jre/lib) --- old/src/share/vm/memory/universe.cpp 2014-02-07 17:50:17.582293996 +0100 +++ new/src/share/vm/memory/universe.cpp 2014-02-07 17:50:17.474294750 +0100 @@ -632,7 +632,6 @@ guarantee(sizeof(oop) % sizeof(HeapWord) == 0, "oop size is not not a multiple of HeapWord size"); TraceTime timer("Genesis", TraceStartupTime); - GC_locker::lock(); // do not allow gc during bootstrapping JavaClasses::compute_hard_coded_offsets(); jint status = Universe::initialize_heap(); @@ -1159,8 +1158,6 @@ MemoryService::add_metaspace_memory_pools(); - GC_locker::unlock(); // allow gc after bootstrapping - MemoryService::set_universe_heap(Universe::_collectedHeap); return true; } --- old/src/share/vm/runtime/thread.cpp 2014-02-07 17:50:17.930291548 +0100 +++ new/src/share/vm/runtime/thread.cpp 2014-02-07 17:50:17.826292281 +0100 @@ -3472,6 +3472,9 @@ // Second phase of bootstrapping, VM is about entering multi-thread mode MemTracker::bootstrap_multi_thread(); + // Do not allow GC during initialization + GC_locker::lock(); + // Initialize global modules jint status = init_globals(); if (status != JNI_OK) { @@ -3541,6 +3544,9 @@ initialize_java_lang_classes(main_thread, CHECK_JNI_ERR); + // After class initialization the GC is ready to run + GC_locker::unlock(); + // We need this for ClassDataSharing - the initial vm.info property is set // with the default value of CDS "sharing" which may be reset through // command line options.