# HG changeset patch # User coleenp # Date 1372776864 -7200 # Node ID cedf20e2a655329f04732f2e67ebbb98cf46cb07 # Parent de2d15ce3d4aa9e3f1594011d3646dad886726bf# Parent 7f11c12d7a90cf3e39124d11144054610c40403d Merge diff -r 7f11c12d7a90 -r cedf20e2a655 src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Mon Jul 01 14:13:12 2013 -0700 +++ b/src/share/vm/memory/metaspace.cpp Tue Jul 02 16:54:24 2013 +0200 @@ -70,7 +70,7 @@ SpecializedChunk = 128, ClassSmallChunk = 256, SmallChunk = 512, - ClassMediumChunk = 1 * K, + ClassMediumChunk = 4 * K, MediumChunk = 8 * K, HumongousChunkGranularity = 8 }; @@ -580,7 +580,6 @@ // Number of small chunks to allocate to a manager // If class space manager, small chunks are unlimited static uint const _small_chunk_limit; - bool has_small_chunk_limit() { return !vs_list()->is_class(); } // Sum of all space in allocated chunks size_t _allocated_blocks_words; @@ -1298,13 +1297,18 @@ bool MetaspaceGC::should_expand(VirtualSpaceList* vsl, size_t word_size) { - size_t committed_capacity_bytes = MetaspaceAux::allocated_capacity_bytes(); // If the user wants a limit, impose one. - size_t max_metaspace_size_bytes = MaxMetaspaceSize; - size_t metaspace_size_bytes = MetaspaceSize; - if (!FLAG_IS_DEFAULT(MaxMetaspaceSize) && - MetaspaceAux::reserved_in_bytes() >= MaxMetaspaceSize) { - return false; + // The reason for someone using this flag is to limit reserved space. So + // for non-class virtual space, compare against virtual spaces that are reserved. + // For class virtual space, we only compare against the committed space, not + // reserved space, because this is a larger space prereserved for compressed + // class pointers. + if (!FLAG_IS_DEFAULT(MaxMetaspaceSize)) { + size_t real_allocated = Metaspace::space_list()->virtual_space_total() + + MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); + if (real_allocated >= MaxMetaspaceSize) { + return false; + } } // Class virtual space should always be expanded. Call GC for the other @@ -1318,11 +1322,12 @@ } - // If the capacity is below the minimum capacity, allow the // expansion. Also set the high-water-mark (capacity_until_GC) // to that minimum capacity so that a GC will not be induced // until that minimum capacity is exceeded. + size_t committed_capacity_bytes = MetaspaceAux::allocated_capacity_bytes(); + size_t metaspace_size_bytes = MetaspaceSize; if (committed_capacity_bytes < metaspace_size_bytes || capacity_until_GC() == 0) { set_capacity_until_GC(metaspace_size_bytes); @@ -1854,13 +1859,11 @@ Metachunk* chunk = chunks_in_use(index); // Count the free space in all the chunk but not the // current chunk from which allocations are still being done. - if (chunk != NULL) { - Metachunk* prev = chunk; - while (chunk != NULL && chunk != current_chunk()) { + while (chunk != NULL) { + if (chunk != current_chunk()) { result += chunk->free_word_size(); - prev = chunk; - chunk = chunk->next(); } + chunk = chunk->next(); } return result; } @@ -1949,8 +1952,7 @@ // chunks will be allocated. size_t chunk_word_size; if (chunks_in_use(MediumIndex) == NULL && - (!has_small_chunk_limit() || - sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit)) { + sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { chunk_word_size = (size_t) small_chunk_size(); if (word_size + Metachunk::overhead() > small_chunk_size()) { chunk_word_size = medium_chunk_size(); @@ -2659,10 +2661,10 @@ // Print total fragmentation for class and data metaspaces separately void MetaspaceAux::print_waste(outputStream* out) { - size_t specialized_waste = 0, small_waste = 0, medium_waste = 0, large_waste = 0; - size_t specialized_count = 0, small_count = 0, medium_count = 0, large_count = 0; - size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0, cls_large_waste = 0; - size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_large_count = 0; + size_t specialized_waste = 0, small_waste = 0, medium_waste = 0; + size_t specialized_count = 0, small_count = 0, medium_count = 0, humongous_count = 0; + size_t cls_specialized_waste = 0, cls_small_waste = 0, cls_medium_waste = 0; + size_t cls_specialized_count = 0, cls_small_count = 0, cls_medium_count = 0, cls_humongous_count = 0; ClassLoaderDataGraphMetaspaceIterator iter; while (iter.repeat()) { @@ -2674,8 +2676,7 @@ small_count += msp->vsm()->sum_count_in_chunks_in_use(SmallIndex); medium_waste += msp->vsm()->sum_waste_in_chunks_in_use(MediumIndex); medium_count += msp->vsm()->sum_count_in_chunks_in_use(MediumIndex); - large_waste += msp->vsm()->sum_waste_in_chunks_in_use(HumongousIndex); - large_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); + humongous_count += msp->vsm()->sum_count_in_chunks_in_use(HumongousIndex); cls_specialized_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(SpecializedIndex); cls_specialized_count += msp->class_vsm()->sum_count_in_chunks_in_use(SpecializedIndex); @@ -2683,20 +2684,23 @@ cls_small_count += msp->class_vsm()->sum_count_in_chunks_in_use(SmallIndex); cls_medium_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(MediumIndex); cls_medium_count += msp->class_vsm()->sum_count_in_chunks_in_use(MediumIndex); - cls_large_waste += msp->class_vsm()->sum_waste_in_chunks_in_use(HumongousIndex); - cls_large_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); + cls_humongous_count += msp->class_vsm()->sum_count_in_chunks_in_use(HumongousIndex); } } out->print_cr("Total fragmentation waste (words) doesn't count free space"); out->print_cr(" data: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " SIZE_FORMAT " small(s) " SIZE_FORMAT ", " - SIZE_FORMAT " medium(s) " SIZE_FORMAT, + SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " + "large count " SIZE_FORMAT, specialized_count, specialized_waste, small_count, - small_waste, medium_count, medium_waste); + small_waste, medium_count, medium_waste, humongous_count); out->print_cr(" class: " SIZE_FORMAT " specialized(s) " SIZE_FORMAT ", " - SIZE_FORMAT " small(s) " SIZE_FORMAT, + SIZE_FORMAT " small(s) " SIZE_FORMAT ", " + SIZE_FORMAT " medium(s) " SIZE_FORMAT ", " + "large count " SIZE_FORMAT, cls_specialized_count, cls_specialized_waste, - cls_small_count, cls_small_waste); + cls_small_count, cls_small_waste, + cls_medium_count, cls_medium_waste, cls_humongous_count); } // Dump global metaspace things from the end of ClassLoaderDataGraph @@ -3037,18 +3041,24 @@ if (Verbose && TraceMetadataChunkAllocation) { gclog_or_tty->print_cr("Metaspace allocation failed for size " SIZE_FORMAT, word_size); - if (loader_data->metaspace_or_null() != NULL) loader_data->metaspace_or_null()->dump(gclog_or_tty); + if (loader_data->metaspace_or_null() != NULL) loader_data->dump(gclog_or_tty); MetaspaceAux::dump(gclog_or_tty); } // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - report_java_out_of_memory("Metadata space"); + const char* space_string = (mdtype == ClassType) ? "Class Metadata space" : + "Metadata space"; + report_java_out_of_memory(space_string); if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR, - "Metadata space"); + space_string); } - THROW_OOP_0(Universe::out_of_memory_error_perm_gen()); + if (mdtype == ClassType) { + THROW_OOP_0(Universe::out_of_memory_error_class_metaspace()); + } else { + THROW_OOP_0(Universe::out_of_memory_error_metaspace()); + } } } return Metablock::initialize(result, word_size); diff -r 7f11c12d7a90 -r cedf20e2a655 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Mon Jul 01 14:13:12 2013 -0700 +++ b/src/share/vm/memory/universe.cpp Tue Jul 02 16:54:24 2013 +0200 @@ -111,7 +111,8 @@ LatestMethodOopCache* Universe::_pd_implies_cache = NULL; ActiveMethodOopsCache* Universe::_reflect_invoke_cache = NULL; oop Universe::_out_of_memory_error_java_heap = NULL; -oop Universe::_out_of_memory_error_perm_gen = NULL; +oop Universe::_out_of_memory_error_metaspace = NULL; +oop Universe::_out_of_memory_error_class_metaspace = NULL; oop Universe::_out_of_memory_error_array_size = NULL; oop Universe::_out_of_memory_error_gc_overhead_limit = NULL; objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; @@ -180,7 +181,8 @@ f->do_oop((oop*)&_the_null_string); f->do_oop((oop*)&_the_min_jint_string); f->do_oop((oop*)&_out_of_memory_error_java_heap); - f->do_oop((oop*)&_out_of_memory_error_perm_gen); + f->do_oop((oop*)&_out_of_memory_error_metaspace); + f->do_oop((oop*)&_out_of_memory_error_class_metaspace); f->do_oop((oop*)&_out_of_memory_error_array_size); f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); f->do_oop((oop*)&_preallocated_out_of_memory_error_array); @@ -563,7 +565,8 @@ // a potential loop which could happen if an out of memory occurs when attempting // to allocate the backtrace. return ((throwable() != Universe::_out_of_memory_error_java_heap) && - (throwable() != Universe::_out_of_memory_error_perm_gen) && + (throwable() != Universe::_out_of_memory_error_metaspace) && + (throwable() != Universe::_out_of_memory_error_class_metaspace) && (throwable() != Universe::_out_of_memory_error_array_size) && (throwable() != Universe::_out_of_memory_error_gc_overhead_limit)); } @@ -1014,7 +1017,8 @@ k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_OutOfMemoryError(), true, CHECK_false); k_h = instanceKlassHandle(THREAD, k); Universe::_out_of_memory_error_java_heap = k_h->allocate_instance(CHECK_false); - Universe::_out_of_memory_error_perm_gen = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_metaspace = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_class_metaspace = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_gc_overhead_limit = k_h->allocate_instance(CHECK_false); @@ -1047,7 +1051,9 @@ java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg()); msg = java_lang_String::create_from_str("Metadata space", CHECK_false); - java_lang_Throwable::set_message(Universe::_out_of_memory_error_perm_gen, msg()); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg()); + msg = java_lang_String::create_from_str("Class Metadata space", CHECK_false); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg()); msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_array_size, msg()); diff -r 7f11c12d7a90 -r cedf20e2a655 src/share/vm/memory/universe.hpp --- a/src/share/vm/memory/universe.hpp Mon Jul 01 14:13:12 2013 -0700 +++ b/src/share/vm/memory/universe.hpp Tue Jul 02 16:54:24 2013 +0200 @@ -178,10 +178,12 @@ static LatestMethodOopCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector static LatestMethodOopCache* _pd_implies_cache; // method for checking protection domain attributes static ActiveMethodOopsCache* _reflect_invoke_cache; // method for security checks - static oop _out_of_memory_error_java_heap; // preallocated error object (no backtrace) - static oop _out_of_memory_error_perm_gen; // preallocated error object (no backtrace) - static oop _out_of_memory_error_array_size;// preallocated error object (no backtrace) - static oop _out_of_memory_error_gc_overhead_limit; // preallocated error object (no backtrace) + // preallocated error objects (no backtrace) + static oop _out_of_memory_error_java_heap; + static oop _out_of_memory_error_metaspace; + static oop _out_of_memory_error_class_metaspace; + static oop _out_of_memory_error_array_size; + static oop _out_of_memory_error_gc_overhead_limit; static Array* _the_empty_int_array; // Canonicalized int array static Array* _the_empty_short_array; // Canonicalized short array @@ -352,7 +354,8 @@ // may or may not have a backtrace. If error has a backtrace then the stack trace is already // filled in. static oop out_of_memory_error_java_heap() { return gen_out_of_memory_error(_out_of_memory_error_java_heap); } - static oop out_of_memory_error_perm_gen() { return gen_out_of_memory_error(_out_of_memory_error_perm_gen); } + static oop out_of_memory_error_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_metaspace); } + static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); } static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } diff -r 7f11c12d7a90 -r cedf20e2a655 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Mon Jul 01 14:13:12 2013 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Jul 02 16:54:24 2013 +0200 @@ -437,10 +437,6 @@ static_field(Universe, _main_thread_group, oop) \ static_field(Universe, _system_thread_group, oop) \ static_field(Universe, _the_empty_class_klass_array, objArrayOop) \ - static_field(Universe, _out_of_memory_error_java_heap, oop) \ - static_field(Universe, _out_of_memory_error_perm_gen, oop) \ - static_field(Universe, _out_of_memory_error_array_size, oop) \ - static_field(Universe, _out_of_memory_error_gc_overhead_limit, oop) \ static_field(Universe, _null_ptr_exception_instance, oop) \ static_field(Universe, _arithmetic_exception_instance, oop) \ static_field(Universe, _vm_exception, oop) \