# HG changeset patch # User stuefe # Date 1500710595 -7200 # Node ID adaac4b80549c17503d4f96257caaf2155791df9 # Parent 33911d9886263772f37dc364d9779d7fef89a267 8185033: On Metaspace OOM, ChunkManager composition should be logged. Reviewed-by: mgerdin, coleenp diff -r 33911d988626 -r adaac4b80549 hotspot/src/share/vm/memory/metaspace.cpp --- a/hotspot/src/share/vm/memory/metaspace.cpp Mon Jul 24 17:26:41 2017 +0000 +++ b/hotspot/src/share/vm/memory/metaspace.cpp Sat Jul 22 10:03:15 2017 +0200 @@ -164,6 +164,18 @@ } void verify_free_chunks_count(); + struct ChunkManagerStatistics { + size_t num_by_type[NumberOfFreeLists]; + size_t single_size_by_type[NumberOfFreeLists]; + size_t total_size_by_type[NumberOfFreeLists]; + size_t num_humongous_chunks; + size_t total_size_humongous_chunks; + }; + + void locked_get_statistics(ChunkManagerStatistics* stat) const; + void get_statistics(ChunkManagerStatistics* stat) const; + static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out); + public: ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size) @@ -181,7 +193,7 @@ ChunkIndex list_index(size_t size); // Map a given index to the chunk size. - size_t size_by_index(ChunkIndex index); + size_t size_by_index(ChunkIndex index) const; // Take a chunk from the ChunkManager. The chunk is expected to be in // the chunk manager (the freelist if non-humongous, the dictionary if @@ -266,6 +278,10 @@ void locked_print_sum_free_chunks(outputStream* st); void print_on(outputStream* st) const; + + // Prints composition for both non-class and (if available) + // class chunk manager. + static void print_all_chunkmanagers(outputStream* out); }; class SmallBlocks : public CHeapObj { @@ -1789,10 +1805,10 @@ return HumongousIndex; } -size_t ChunkManager::size_by_index(ChunkIndex index) { +size_t ChunkManager::size_by_index(ChunkIndex index) const { index_bounds_check(index); assert(index != HumongousIndex, "Do not call for humongous chunks."); - return free_chunks(index)->size(); + return _free_chunks[index].size(); } void ChunkManager::locked_verify_free_chunks_total() { @@ -2045,7 +2061,61 @@ } void ChunkManager::print_on(outputStream* out) const { - const_cast(this)->humongous_dictionary()->report_statistics(out); + _humongous_dictionary.report_statistics(out); +} + +void ChunkManager::locked_get_statistics(ChunkManagerStatistics* stat) const { + assert_lock_strong(SpaceManager::expand_lock()); + for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { + stat->num_by_type[i] = num_free_chunks(i); + stat->single_size_by_type[i] = size_by_index(i); + stat->total_size_by_type[i] = size_free_chunks_in_bytes(i); + } + stat->num_humongous_chunks = num_free_chunks(HumongousIndex); + stat->total_size_humongous_chunks = size_free_chunks_in_bytes(HumongousIndex); +} + +void ChunkManager::get_statistics(ChunkManagerStatistics* stat) const { + MutexLockerEx cl(SpaceManager::expand_lock(), + Mutex::_no_safepoint_check_flag); + locked_get_statistics(stat); +} + +void ChunkManager::print_statistics(const ChunkManagerStatistics* stat, outputStream* out) { + size_t total = 0; + for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { + out->print_cr(" " SIZE_FORMAT " %s (" SIZE_FORMAT " bytes) chunks, total " SIZE_FORMAT " bytes", + stat->num_by_type[i], chunk_size_name(i), + stat->single_size_by_type[i], + stat->total_size_by_type[i]); + total += stat->total_size_by_type[i]; + } + out->print_cr(" " SIZE_FORMAT " humongous chunks, total " SIZE_FORMAT " bytes", + stat->num_humongous_chunks, stat->total_size_humongous_chunks); + total += stat->total_size_humongous_chunks; + out->print_cr(" total size: " SIZE_FORMAT ".", total); +} + +void ChunkManager::print_all_chunkmanagers(outputStream* out) { + // Note: keep lock protection only to retrieving statistics; keep printing + // out of lock protection + ChunkManagerStatistics stat; + out->print_cr("Chunkmanager (non-class):"); + const ChunkManager* const non_class_cm = Metaspace::chunk_manager_metadata(); + if (non_class_cm != NULL) { + non_class_cm->get_statistics(&stat); + ChunkManager::print_statistics(&stat, out); + } else { + out->print_cr("unavailable."); + } + out->print_cr("Chunkmanager (class):"); + const ChunkManager* const class_cm = Metaspace::chunk_manager_class(); + if (class_cm != NULL) { + class_cm->get_statistics(&stat); + ChunkManager::print_statistics(&stat, out); + } else { + out->print_cr("unavailable."); + } } // SpaceManager methods @@ -3670,6 +3740,7 @@ loader_data->dump(&ls); } MetaspaceAux::dump(&ls); + ChunkManager::print_all_chunkmanagers(&ls); } bool out_of_compressed_class_space = false;