Mon, 08 Jan 2018 22:39:26 -0800
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
src/share/vm/prims/jni.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Wed Jan 03 14:23:36 2018 -0800 1.2 +++ b/.hgtags Mon Jan 08 22:39:26 2018 -0800 1.3 @@ -1127,3 +1127,4 @@ 1.4 69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12 1.5 f299cf0b7baea1ae85f139f97adb9ab5499f402a jdk8u172-b00 1.6 d10254debf7c1342416062bf1ba5258f16a8ce00 jdk8u172-b01 1.7 +653d9e0cd3f4023675c9eece7f0d563287f1d34f jdk8u172-b02
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/share/vm/classfile/classLoaderStats.cpp Mon Jan 08 22:39:26 2018 -0800 2.3 @@ -0,0 +1,167 @@ 2.4 +/* 2.5 + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + * 2.26 + */ 2.27 + 2.28 +#include "precompiled.hpp" 2.29 +#include "classfile/classLoaderStats.hpp" 2.30 +#include "utilities/globalDefinitions.hpp" 2.31 + 2.32 + 2.33 +class ClassStatsClosure : public KlassClosure { 2.34 +public: 2.35 + int _num_classes; 2.36 + 2.37 + ClassStatsClosure() : 2.38 + _num_classes(0) { 2.39 + } 2.40 + 2.41 + virtual void do_klass(Klass* k) { 2.42 + _num_classes++; 2.43 + } 2.44 +}; 2.45 + 2.46 + 2.47 +void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) { 2.48 + oop cl = cld->class_loader(); 2.49 + ClassLoaderStats* cls; 2.50 + 2.51 + // The hashtable key is the ClassLoader oop since we want to account 2.52 + // for "real" classes and anonymous classes together 2.53 + ClassLoaderStats** cls_ptr = _stats->get(cl); 2.54 + if (cls_ptr == NULL) { 2.55 + cls = new ClassLoaderStats(); 2.56 + _stats->put(cl, cls); 2.57 + _total_loaders++; 2.58 + } else { 2.59 + cls = *cls_ptr; 2.60 + } 2.61 + 2.62 + if (!cld->is_anonymous()) { 2.63 + cls->_cld = cld; 2.64 + } 2.65 + 2.66 + cls->_class_loader = cl; 2.67 + if (cl != NULL) { 2.68 + cls->_parent = java_lang_ClassLoader::parent(cl); 2.69 + addEmptyParents(cls->_parent); 2.70 + } 2.71 + 2.72 + ClassStatsClosure csc; 2.73 + cld->classes_do(&csc); 2.74 + if(cld->is_anonymous()) { 2.75 + cls->_anon_classes_count += csc._num_classes; 2.76 + } else { 2.77 + cls->_classes_count = csc._num_classes; 2.78 + } 2.79 + _total_classes += csc._num_classes; 2.80 + 2.81 + Metaspace* ms = cld->metaspace_or_null(); 2.82 + if (ms != NULL) { 2.83 + if(cld->is_anonymous()) { 2.84 + cls->_anon_chunk_sz += ms->allocated_chunks_bytes(); 2.85 + cls->_anon_block_sz += ms->allocated_blocks_bytes(); 2.86 + } else { 2.87 + cls->_chunk_sz = ms->allocated_chunks_bytes(); 2.88 + cls->_block_sz = ms->allocated_blocks_bytes(); 2.89 + } 2.90 + _total_chunk_sz += ms->allocated_chunks_bytes(); 2.91 + _total_block_sz += ms->allocated_blocks_bytes(); 2.92 + } 2.93 +} 2.94 + 2.95 + 2.96 +// Handles the difference in pointer width on 32 and 64 bit platforms 2.97 +#ifdef _LP64 2.98 + #define SPACE "%8s" 2.99 +#else 2.100 + #define SPACE "%s" 2.101 +#endif 2.102 + 2.103 + 2.104 +bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats* const& cls) { 2.105 + Klass* class_loader_klass = (cls->_class_loader == NULL ? NULL : cls->_class_loader->klass()); 2.106 + Klass* parent_klass = (cls->_parent == NULL ? NULL : cls->_parent->klass()); 2.107 + 2.108 + _out->print(INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " ", 2.109 + p2i(class_loader_klass), p2i(parent_klass), p2i(cls->_cld), 2.110 + cls->_classes_count, 2.111 + cls->_chunk_sz, cls->_block_sz); 2.112 + if (class_loader_klass != NULL) { 2.113 + _out->print("%s", class_loader_klass->external_name()); 2.114 + } else { 2.115 + _out->print("<boot class loader>"); 2.116 + } 2.117 + _out->cr(); 2.118 + if (cls->_anon_classes_count > 0) { 2.119 + _out->print_cr(SPACE SPACE SPACE " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " + unsafe anonymous classes", 2.120 + "", "", "", 2.121 + cls->_anon_classes_count, 2.122 + cls->_anon_chunk_sz, cls->_anon_block_sz); 2.123 + } 2.124 + return true; 2.125 +} 2.126 + 2.127 + 2.128 +void ClassLoaderStatsClosure::print() { 2.129 + _out->print_cr("ClassLoader" SPACE " Parent" SPACE " CLD*" SPACE " Classes ChunkSz BlockSz Type", "", "", ""); 2.130 + _stats->iterate(this); 2.131 + _out->print("Total = " UINTX_FORMAT_W(-6), _total_loaders); 2.132 + _out->print(SPACE SPACE SPACE " ", "", "", ""); 2.133 + _out->print_cr(UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " ", 2.134 + _total_classes, 2.135 + _total_chunk_sz, 2.136 + _total_block_sz); 2.137 + _out->print_cr("ChunkSz: Total size of all allocated metaspace chunks"); 2.138 + _out->print_cr("BlockSz: Total size of all allocated metaspace blocks (each chunk has several blocks)"); 2.139 +} 2.140 + 2.141 + 2.142 +void ClassLoaderStatsClosure::addEmptyParents(oop cl) { 2.143 + while (cl != NULL && java_lang_ClassLoader::loader_data(cl) == NULL) { 2.144 + // This classloader has not loaded any classes 2.145 + ClassLoaderStats** cls_ptr = _stats->get(cl); 2.146 + if (cls_ptr == NULL) { 2.147 + // It does not exist in our table - add it 2.148 + ClassLoaderStats* cls = new ClassLoaderStats(); 2.149 + cls->_class_loader = cl; 2.150 + cls->_parent = java_lang_ClassLoader::parent(cl); 2.151 + _stats->put(cl, cls); 2.152 + _total_loaders++; 2.153 + } 2.154 + 2.155 + cl = java_lang_ClassLoader::parent(cl); 2.156 + } 2.157 +} 2.158 + 2.159 + 2.160 +void ClassLoaderStatsVMOperation::doit() { 2.161 + ClassLoaderStatsClosure clsc (_out); 2.162 + ClassLoaderDataGraph::cld_do(&clsc); 2.163 + clsc.print(); 2.164 +} 2.165 + 2.166 + 2.167 +void ClassLoaderStatsDCmd::execute(DCmdSource source, TRAPS) { 2.168 + ClassLoaderStatsVMOperation op(output()); 2.169 + VMThread::execute(&op); 2.170 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/share/vm/classfile/classLoaderStats.hpp Mon Jan 08 22:39:26 2018 -0800 3.3 @@ -0,0 +1,152 @@ 3.4 +/* 3.5 + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + * 3.26 + */ 3.27 + 3.28 +#ifndef SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP 3.29 +#define SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP 3.30 + 3.31 + 3.32 +#include "classfile/classLoaderData.hpp" 3.33 +#include "oops/klass.hpp" 3.34 +#include "oops/oopsHierarchy.hpp" 3.35 +#include "runtime/vm_operations.hpp" 3.36 +#include "services/diagnosticCommand.hpp" 3.37 +#include "utilities/resourceHash.hpp" 3.38 + 3.39 + 3.40 +class ClassLoaderStatsDCmd : public DCmd { 3.41 +public: 3.42 + ClassLoaderStatsDCmd(outputStream* output, bool heap) : 3.43 + DCmd(output, heap) { 3.44 + } 3.45 + 3.46 + static const char* name() { 3.47 + return "VM.classloader_stats"; 3.48 + } 3.49 + 3.50 + static const char* description() { 3.51 + return "Print statistics about all ClassLoaders."; 3.52 + } 3.53 + 3.54 + static const char* impact() { 3.55 + return "Low"; 3.56 + } 3.57 + 3.58 + virtual void execute(DCmdSource source, TRAPS); 3.59 + 3.60 + static int num_arguments() { 3.61 + return 0; 3.62 + } 3.63 + 3.64 + static const JavaPermission permission() { 3.65 + JavaPermission p = {"java.lang.management.ManagementPermission", 3.66 + "monitor", NULL}; 3.67 + return p; 3.68 + } 3.69 +}; 3.70 + 3.71 + 3.72 +class ClassLoaderStats : public ResourceObj { 3.73 +public: 3.74 + ClassLoaderData* _cld; 3.75 + oop _class_loader; 3.76 + oop _parent; 3.77 + 3.78 + size_t _chunk_sz; 3.79 + size_t _block_sz; 3.80 + uintx _classes_count; 3.81 + 3.82 + size_t _anon_chunk_sz; 3.83 + size_t _anon_block_sz; 3.84 + uintx _anon_classes_count; 3.85 + 3.86 + ClassLoaderStats() : 3.87 + _cld(0), 3.88 + _class_loader(0), 3.89 + _parent(0), 3.90 + _chunk_sz(0), 3.91 + _block_sz(0), 3.92 + _classes_count(0), 3.93 + _anon_block_sz(0), 3.94 + _anon_chunk_sz(0), 3.95 + _anon_classes_count(0) { 3.96 + } 3.97 +}; 3.98 + 3.99 + 3.100 +class ClassLoaderStatsClosure : public CLDClosure { 3.101 +protected: 3.102 + static bool oop_equals(oop const& s1, oop const& s2) { 3.103 + return s1 == s2; 3.104 + } 3.105 + 3.106 + static unsigned oop_hash(oop const& s1) { 3.107 + unsigned hash = (unsigned)((uintptr_t)&s1); 3.108 + return hash ^ (hash >> LogMinObjAlignment); 3.109 + } 3.110 + 3.111 + typedef ResourceHashtable<oop, ClassLoaderStats*, 3.112 + ClassLoaderStatsClosure::oop_hash, ClassLoaderStatsClosure::oop_equals> StatsTable; 3.113 + 3.114 + outputStream* _out; 3.115 + StatsTable* _stats; 3.116 + uintx _total_loaders; 3.117 + uintx _total_classes; 3.118 + size_t _total_chunk_sz; 3.119 + size_t _total_block_sz; 3.120 + 3.121 +public: 3.122 + ClassLoaderStatsClosure(outputStream* out) : 3.123 + _out(out), 3.124 + _total_loaders(0), 3.125 + _total_block_sz(0), 3.126 + _total_chunk_sz(0), 3.127 + _total_classes(0), 3.128 + _stats(new StatsTable()) { 3.129 + } 3.130 + 3.131 + virtual void do_cld(ClassLoaderData* cld); 3.132 + virtual bool do_entry(oop const& key, ClassLoaderStats* const& cls); 3.133 + void print(); 3.134 + 3.135 +private: 3.136 + void addEmptyParents(oop cl); 3.137 +}; 3.138 + 3.139 + 3.140 +class ClassLoaderStatsVMOperation : public VM_Operation { 3.141 + outputStream* _out; 3.142 + 3.143 +public: 3.144 + ClassLoaderStatsVMOperation(outputStream* out) : 3.145 + _out(out) { 3.146 + } 3.147 + 3.148 + VMOp_Type type() const { 3.149 + return VMOp_ClassLoaderStatsOperation; 3.150 + } 3.151 + 3.152 + void doit(); 3.153 +}; 3.154 + 3.155 +#endif // SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
4.1 --- a/src/share/vm/memory/metaspace.cpp Wed Jan 03 14:23:36 2018 -0800 4.2 +++ b/src/share/vm/memory/metaspace.cpp Mon Jan 08 22:39:26 2018 -0800 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -154,7 +154,7 @@ 4.11 4.12 // Map a size to a list index assuming that there are lists 4.13 // for special, small, medium, and humongous chunks. 4.14 - static ChunkIndex list_index(size_t size); 4.15 + ChunkIndex list_index(size_t size); 4.16 4.17 // Remove the chunk from its freelist. It is 4.18 // expected to be on one of the _free_chunks[] lists. 4.19 @@ -706,6 +706,7 @@ 4.20 size_t allocated_blocks_words() const { return _allocated_blocks_words; } 4.21 size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; } 4.22 size_t allocated_chunks_words() const { return _allocated_chunks_words; } 4.23 + size_t allocated_chunks_bytes() const { return _allocated_chunks_words * BytesPerWord; } 4.24 size_t allocated_chunks_count() const { return _allocated_chunks_count; } 4.25 4.26 bool is_humongous(size_t word_size) { return word_size > medium_chunk_size(); } 4.27 @@ -1751,7 +1752,11 @@ 4.28 st->print_cr("Sum free chunk total " SIZE_FORMAT " count " SIZE_FORMAT, 4.29 sum_free_chunks(), sum_free_chunks_count()); 4.30 } 4.31 + 4.32 ChunkList* ChunkManager::free_chunks(ChunkIndex index) { 4.33 + assert(index == SpecializedIndex || index == SmallIndex || index == MediumIndex, 4.34 + err_msg("Bad index: %d", (int)index)); 4.35 + 4.36 return &_free_chunks[index]; 4.37 } 4.38 4.39 @@ -1863,7 +1868,7 @@ 4.40 } 4.41 4.42 assert((word_size <= chunk->word_size()) || 4.43 - list_index(chunk->word_size() == HumongousIndex), 4.44 + (list_index(chunk->word_size()) == HumongousIndex), 4.45 "Non-humongous variable sized chunk"); 4.46 if (TraceMetadataChunkAllocation) { 4.47 size_t list_count; 4.48 @@ -2357,22 +2362,18 @@ 4.49 } 4.50 4.51 ChunkIndex ChunkManager::list_index(size_t size) { 4.52 - switch (size) { 4.53 - case SpecializedChunk: 4.54 - assert(SpecializedChunk == ClassSpecializedChunk, 4.55 - "Need branch for ClassSpecializedChunk"); 4.56 - return SpecializedIndex; 4.57 - case SmallChunk: 4.58 - case ClassSmallChunk: 4.59 - return SmallIndex; 4.60 - case MediumChunk: 4.61 - case ClassMediumChunk: 4.62 - return MediumIndex; 4.63 - default: 4.64 - assert(size > MediumChunk || size > ClassMediumChunk, 4.65 - "Not a humongous chunk"); 4.66 - return HumongousIndex; 4.67 + if (free_chunks(SpecializedIndex)->size() == size) { 4.68 + return SpecializedIndex; 4.69 } 4.70 + if (free_chunks(SmallIndex)->size() == size) { 4.71 + return SmallIndex; 4.72 + } 4.73 + if (free_chunks(MediumIndex)->size() == size) { 4.74 + return MediumIndex; 4.75 + } 4.76 + 4.77 + assert(size > free_chunks(MediumIndex)->size(), "Not a humongous chunk"); 4.78 + return HumongousIndex; 4.79 } 4.80 4.81 void SpaceManager::deallocate(MetaWord* p, size_t word_size) { 4.82 @@ -2394,7 +2395,7 @@ 4.83 4.84 // Find the correct list and and set the current 4.85 // chunk for that list. 4.86 - ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); 4.87 + ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size()); 4.88 4.89 if (index != HumongousIndex) { 4.90 retire_current_chunk(); 4.91 @@ -3463,6 +3464,16 @@ 4.92 return capacity_words_slow(mdtype) * BytesPerWord; 4.93 } 4.94 4.95 +size_t Metaspace::allocated_blocks_bytes() const { 4.96 + return vsm()->allocated_blocks_bytes() + 4.97 + (using_class_space() ? class_vsm()->allocated_blocks_bytes() : 0); 4.98 +} 4.99 + 4.100 +size_t Metaspace::allocated_chunks_bytes() const { 4.101 + return vsm()->allocated_chunks_bytes() + 4.102 + (using_class_space() ? class_vsm()->allocated_chunks_bytes() : 0); 4.103 +} 4.104 + 4.105 void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { 4.106 if (SafepointSynchronize::is_at_safepoint()) { 4.107 if (DumpSharedSpaces && PrintSharedSpaces) { 4.108 @@ -4020,4 +4031,40 @@ 4.109 SpaceManagerTest::test_adjust_initial_chunk_size(); 4.110 } 4.111 4.112 +// The following test is placed here instead of a gtest / unittest file 4.113 +// because the ChunkManager class is only available in this file. 4.114 +void ChunkManager_test_list_index() { 4.115 + ChunkManager manager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk); 4.116 + 4.117 + // Test previous bug where a query for a humongous class metachunk, 4.118 + // incorrectly matched the non-class medium metachunk size. 4.119 + { 4.120 + assert(MediumChunk > ClassMediumChunk, "Precondition for test"); 4.121 + 4.122 + ChunkIndex index = manager.list_index(MediumChunk); 4.123 + 4.124 + assert(index == HumongousIndex, 4.125 + err_msg("Requested size is larger than ClassMediumChunk," 4.126 + " so should return HumongousIndex. Got index: %d", (int)index)); 4.127 + } 4.128 + 4.129 + // Check the specified sizes as well. 4.130 + { 4.131 + ChunkIndex index = manager.list_index(ClassSpecializedChunk); 4.132 + assert(index == SpecializedIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); 4.133 + } 4.134 + { 4.135 + ChunkIndex index = manager.list_index(ClassSmallChunk); 4.136 + assert(index == SmallIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); 4.137 + } 4.138 + { 4.139 + ChunkIndex index = manager.list_index(ClassMediumChunk); 4.140 + assert(index == MediumIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); 4.141 + } 4.142 + { 4.143 + ChunkIndex index = manager.list_index(ClassMediumChunk + 1); 4.144 + assert(index == HumongousIndex, err_msg("Wrong index returned. Got index: %d", (int)index)); 4.145 + } 4.146 +} 4.147 + 4.148 #endif
5.1 --- a/src/share/vm/memory/metaspace.hpp Wed Jan 03 14:23:36 2018 -0800 5.2 +++ b/src/share/vm/memory/metaspace.hpp Mon Jan 08 22:39:26 2018 -0800 5.3 @@ -232,6 +232,9 @@ 5.4 size_t used_bytes_slow(MetadataType mdtype) const; 5.5 size_t capacity_bytes_slow(MetadataType mdtype) const; 5.6 5.7 + size_t allocated_blocks_bytes() const; 5.8 + size_t allocated_chunks_bytes() const; 5.9 + 5.10 static MetaWord* allocate(ClassLoaderData* loader_data, size_t word_size, 5.11 bool read_only, MetaspaceObj::Type type, TRAPS); 5.12 void deallocate(MetaWord* ptr, size_t byte_size, bool is_class);
6.1 --- a/src/share/vm/prims/jni.cpp Wed Jan 03 14:23:36 2018 -0800 6.2 +++ b/src/share/vm/prims/jni.cpp Mon Jan 08 22:39:26 2018 -0800 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 6.7 * Copyright (c) 2012 Red Hat, Inc. 6.8 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.9 * 6.10 @@ -5106,6 +5106,7 @@ 6.11 void TestBufferingOopClosure_test(); 6.12 void TestCodeCacheRemSet_test(); 6.13 void FreeRegionList_test(); 6.14 +void ChunkManager_test_list_index(); 6.15 #endif 6.16 6.17 void execute_internal_vm_tests() { 6.18 @@ -5139,6 +5140,7 @@ 6.19 run_unit_test(TestG1BiasedArray_test()); 6.20 run_unit_test(HeapRegionRemSet::test_prt()); 6.21 run_unit_test(SpaceManager_test_adjust_initial_chunk_size()); 6.22 + run_unit_test(ChunkManager_test_list_index()); 6.23 run_unit_test(TestBufferingOopClosure_test()); 6.24 run_unit_test(TestCodeCacheRemSet_test()); 6.25 if (UseG1GC) {
7.1 --- a/src/share/vm/runtime/vm_operations.hpp Wed Jan 03 14:23:36 2018 -0800 7.2 +++ b/src/share/vm/runtime/vm_operations.hpp Mon Jan 08 22:39:26 2018 -0800 7.3 @@ -97,6 +97,7 @@ 7.4 template(LinuxDllLoad) \ 7.5 template(RotateGCLog) \ 7.6 template(WhiteBoxOperation) \ 7.7 + template(ClassLoaderStatsOperation) \ 7.8 7.9 class VM_Operation: public CHeapObj<mtInternal> { 7.10 public:
8.1 --- a/src/share/vm/services/diagnosticCommand.cpp Wed Jan 03 14:23:36 2018 -0800 8.2 +++ b/src/share/vm/services/diagnosticCommand.cpp Mon Jan 08 22:39:26 2018 -0800 8.3 @@ -23,6 +23,7 @@ 8.4 */ 8.5 8.6 #include "precompiled.hpp" 8.7 +#include "classfile/classLoaderStats.hpp" 8.8 #include "gc_implementation/shared/vmGCOperations.hpp" 8.9 #include "runtime/javaCalls.hpp" 8.10 #include "runtime/os.hpp" 8.11 @@ -61,6 +62,7 @@ 8.12 #endif // INCLUDE_SERVICES 8.13 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false)); 8.14 DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false)); 8.15 + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false)); 8.16 8.17 // Enhanced JMX Agent Support 8.18 // These commands won't be exported via the DiagnosticCommandMBean until an
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/serviceability/dcmd/ClassLoaderStatsTest.java Mon Jan 08 22:39:26 2018 -0800 9.3 @@ -0,0 +1,155 @@ 9.4 +/* 9.5 + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + */ 9.26 + 9.27 +/* 9.28 + * @test 9.29 + * 9.30 + * @build ClassLoaderStatsTest DcmdUtil 9.31 + * @run main ClassLoaderStatsTest 9.32 + */ 9.33 + 9.34 +import java.io.BufferedReader; 9.35 +import java.io.File; 9.36 +import java.io.FileInputStream; 9.37 +import java.io.IOException; 9.38 +import java.io.StringReader; 9.39 +import java.nio.ByteBuffer; 9.40 +import java.nio.channels.FileChannel; 9.41 +import java.util.regex.Matcher; 9.42 +import java.util.regex.Pattern; 9.43 + 9.44 +public class ClassLoaderStatsTest { 9.45 + 9.46 + // ClassLoader Parent CLD* Classes ChunkSz BlockSz Type 9.47 + // 0x00000007c0215928 0x0000000000000000 0x0000000000000000 0 0 0 org.eclipse.osgi.baseadaptor.BaseAdaptor$1 9.48 + // 0x00000007c0009868 0x0000000000000000 0x00007fc52aebcc80 1 6144 3768 sun.reflect.DelegatingClassLoader 9.49 + // 0x00000007c0009868 0x0000000000000000 0x00007fc52b8916d0 1 6144 3688 sun.reflect.DelegatingClassLoader 9.50 + // 0x00000007c0009868 0x00000007c0038ba8 0x00007fc52afb8760 1 6144 3688 sun.reflect.DelegatingClassLoader 9.51 + // 0x00000007c0009868 0x0000000000000000 0x00007fc52afbb1a0 1 6144 3688 sun.reflect.DelegatingClassLoader 9.52 + // 0x0000000000000000 0x0000000000000000 0x00007fc523416070 5019 30060544 29956216 <boot classloader> 9.53 + // 455 1210368 672848 + unsafe anonymous classes 9.54 + // 0x00000007c016b5c8 0x00000007c0038ba8 0x00007fc52a995000 5 8192 5864 org.netbeans.StandardModule$OneModuleClassLoader 9.55 + // 0x00000007c0009868 0x00000007c016b5c8 0x00007fc52ac13640 1 6144 3896 sun.reflect.DelegatingClassLoader 9.56 + // ... 9.57 + 9.58 + static Pattern clLine = Pattern.compile("0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*0x\\p{XDigit}*\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*(.*)"); 9.59 + static Pattern anonLine = Pattern.compile("\\s*(\\d*)\\s*(\\d*)\\s*(\\d*)\\s*.*"); 9.60 + 9.61 + public static DummyClassLoader dummyloader; 9.62 + 9.63 + public static void main(String arg[]) throws Exception { 9.64 + 9.65 + // create a classloader and load our special class 9.66 + dummyloader = new DummyClassLoader(); 9.67 + Class<?> c = Class.forName("TestClass", true, dummyloader); 9.68 + if (c.getClassLoader() != dummyloader) { 9.69 + throw new RuntimeException("TestClass defined by wrong classloader: " + c.getClassLoader()); 9.70 + } 9.71 + 9.72 + String result = DcmdUtil.executeDcmd("VM.classloader_stats"); 9.73 + BufferedReader r = new BufferedReader(new StringReader(result)); 9.74 + String line; 9.75 + while((line = r.readLine()) != null) { 9.76 + Matcher m = clLine.matcher(line); 9.77 + if (m.matches()) { 9.78 + // verify that DummyClassLoader has loaded 1 class and 1 anonymous class 9.79 + if (m.group(4).equals("ClassLoaderStatsTest$DummyClassLoader")) { 9.80 + System.out.println("line: " + line); 9.81 + if (!m.group(1).equals("1")) { 9.82 + throw new Exception("Should have loaded 1 class: " + line); 9.83 + } 9.84 + checkPositiveInt(m.group(2)); 9.85 + checkPositiveInt(m.group(3)); 9.86 + 9.87 + String next = r.readLine(); 9.88 + System.out.println("next: " + next); 9.89 + Matcher m1 = anonLine.matcher(next); 9.90 + m1.matches(); 9.91 + if (!m1.group(1).equals("1")) { 9.92 + throw new Exception("Should have loaded 1 anonymous class, but found : " + m1.group(1)); 9.93 + } 9.94 + checkPositiveInt(m1.group(2)); 9.95 + checkPositiveInt(m1.group(3)); 9.96 + } 9.97 + } 9.98 + } 9.99 + } 9.100 + 9.101 + private static void checkPositiveInt(String s) throws Exception { 9.102 + if (Integer.parseInt(s) <= 0) { 9.103 + throw new Exception("Value should have been > 0: " + s); 9.104 + } 9.105 + } 9.106 + 9.107 + public static class DummyClassLoader extends ClassLoader { 9.108 + 9.109 + public static final String CLASS_NAME = "TestClass"; 9.110 + 9.111 + static ByteBuffer readClassFile(String name) 9.112 + { 9.113 + File f = new File(System.getProperty("test.classes", "."), 9.114 + name); 9.115 + try (FileInputStream fin = new FileInputStream(f); 9.116 + FileChannel fc = fin.getChannel()) 9.117 + { 9.118 + return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 9.119 + } catch (IOException e) { 9.120 + throw new RuntimeException("Can't open file: " + name, e); 9.121 + } 9.122 + } 9.123 + 9.124 + protected Class<?> loadClass(String name, boolean resolve) 9.125 + throws ClassNotFoundException 9.126 + { 9.127 + Class<?> c; 9.128 + if (!"TestClass".equals(name)) { 9.129 + c = super.loadClass(name, resolve); 9.130 + } else { 9.131 + // should not delegate to the system class loader 9.132 + c = findClass(name); 9.133 + if (resolve) { 9.134 + resolveClass(c); 9.135 + } 9.136 + } 9.137 + return c; 9.138 + } 9.139 + 9.140 + protected Class<?> findClass(String name) 9.141 + throws ClassNotFoundException 9.142 + { 9.143 + if (!"TestClass".equals(name)) { 9.144 + throw new ClassNotFoundException("Unexpected class: " + name); 9.145 + } 9.146 + return defineClass(name, readClassFile(name + ".class"), null); 9.147 + } 9.148 + } /* DummyClassLoader */ 9.149 + 9.150 +} 9.151 + 9.152 +class TestClass { 9.153 + static { 9.154 + // force creation of anonymous class (for the lambdaform) 9.155 + Runnable r = () -> System.out.println("Hello"); 9.156 + r.run(); 9.157 + } 9.158 +}