Wed, 20 Aug 2014 08:41:15 -0400
8054546: NMT2 leaks memory
Summary: Fixed memory leak in NMT by baselining memory in c heap instead of an arena.
Reviewed-by: coleenp, minqi
1.1 --- a/src/share/vm/services/mallocTracker.hpp Tue Aug 19 09:05:55 2014 -0400 1.2 +++ b/src/share/vm/services/mallocTracker.hpp Wed Aug 20 08:41:15 2014 -0400 1.3 @@ -171,8 +171,9 @@ 1.4 // Total malloc'd memory used by arenas 1.5 size_t total_arena() const; 1.6 1.7 - inline size_t thread_count() { 1.8 - return by_type(mtThreadStack)->malloc_count(); 1.9 + inline size_t thread_count() const { 1.10 + MallocMemorySnapshot* s = const_cast<MallocMemorySnapshot*>(this); 1.11 + return s->by_type(mtThreadStack)->malloc_count(); 1.12 } 1.13 1.14 void reset();
2.1 --- a/src/share/vm/services/memBaseline.cpp Tue Aug 19 09:05:55 2014 -0400 2.2 +++ b/src/share/vm/services/memBaseline.cpp Wed Aug 20 08:41:15 2014 -0400 2.3 @@ -70,15 +70,13 @@ 2.4 */ 2.5 class MallocAllocationSiteWalker : public MallocSiteWalker { 2.6 private: 2.7 - SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> 2.8 - _malloc_sites; 2.9 + SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites; 2.10 size_t _count; 2.11 2.12 // Entries in MallocSiteTable with size = 0 and count = 0, 2.13 // when the malloc site is not longer there. 2.14 public: 2.15 - MallocAllocationSiteWalker(Arena* arena) : _count(0), _malloc_sites(arena) { 2.16 - } 2.17 + MallocAllocationSiteWalker() : _count(0) { } 2.18 2.19 inline size_t count() const { return _count; } 2.20 2.21 @@ -109,13 +107,12 @@ 2.22 // Walk all virtual memory regions for baselining 2.23 class VirtualMemoryAllocationWalker : public VirtualMemoryWalker { 2.24 private: 2.25 - SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base, ResourceObj::ARENA> 2.26 + SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base> 2.27 _virtual_memory_regions; 2.28 size_t _count; 2.29 2.30 public: 2.31 - VirtualMemoryAllocationWalker(Arena* a) : _count(0), _virtual_memory_regions(a) { 2.32 - } 2.33 + VirtualMemoryAllocationWalker() : _count(0) { } 2.34 2.35 bool do_allocation_site(const ReservedMemoryRegion* rgn) { 2.36 if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) { 2.37 @@ -136,39 +133,30 @@ 2.38 2.39 2.40 bool MemBaseline::baseline_summary() { 2.41 - assert(_malloc_memory_snapshot == NULL, "Malloc baseline not yet reset"); 2.42 - assert(_virtual_memory_snapshot == NULL, "Virtual baseline not yet reset"); 2.43 - 2.44 - _malloc_memory_snapshot = new (arena()) MallocMemorySnapshot(); 2.45 - _virtual_memory_snapshot = new (arena()) VirtualMemorySnapshot(); 2.46 - if (_malloc_memory_snapshot == NULL || _virtual_memory_snapshot == NULL) { 2.47 - return false; 2.48 - } 2.49 - MallocMemorySummary::snapshot(_malloc_memory_snapshot); 2.50 - VirtualMemorySummary::snapshot(_virtual_memory_snapshot); 2.51 + MallocMemorySummary::snapshot(&_malloc_memory_snapshot); 2.52 + VirtualMemorySummary::snapshot(&_virtual_memory_snapshot); 2.53 return true; 2.54 } 2.55 2.56 bool MemBaseline::baseline_allocation_sites() { 2.57 - assert(arena() != NULL, "Just check"); 2.58 // Malloc allocation sites 2.59 - MallocAllocationSiteWalker malloc_walker(arena()); 2.60 + MallocAllocationSiteWalker malloc_walker; 2.61 if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) { 2.62 return false; 2.63 } 2.64 2.65 - _malloc_sites.set_head(malloc_walker.malloc_sites()->head()); 2.66 + _malloc_sites.move(malloc_walker.malloc_sites()); 2.67 // The malloc sites are collected in size order 2.68 _malloc_sites_order = by_size; 2.69 2.70 // Virtual memory allocation sites 2.71 - VirtualMemoryAllocationWalker virtual_memory_walker(arena()); 2.72 + VirtualMemoryAllocationWalker virtual_memory_walker; 2.73 if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { 2.74 return false; 2.75 } 2.76 2.77 // Virtual memory allocations are collected in call stack order 2.78 - _virtual_memory_allocations.set_head(virtual_memory_walker.virtual_memory_allocations()->head()); 2.79 + _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations()); 2.80 2.81 if (!aggregate_virtual_memory_allocation_sites()) { 2.82 return false; 2.83 @@ -180,11 +168,6 @@ 2.84 } 2.85 2.86 bool MemBaseline::baseline(bool summaryOnly) { 2.87 - if (arena() == NULL) { 2.88 - _arena = new (std::nothrow, mtNMT) Arena(mtNMT); 2.89 - if (arena() == NULL) return false; 2.90 - } 2.91 - 2.92 reset(); 2.93 2.94 _class_count = InstanceKlass::number_of_instance_classes(); 2.95 @@ -211,8 +194,7 @@ 2.96 } 2.97 2.98 bool MemBaseline::aggregate_virtual_memory_allocation_sites() { 2.99 - SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site, ResourceObj::ARENA> 2.100 - allocation_sites(arena()); 2.101 + SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites; 2.102 2.103 VirtualMemoryAllocationIterator itr = virtual_memory_allocations(); 2.104 const ReservedMemoryRegion* rgn; 2.105 @@ -230,12 +212,12 @@ 2.106 site->commit_memory(rgn->committed_size()); 2.107 } 2.108 2.109 - _virtual_memory_sites.set_head(allocation_sites.head()); 2.110 + _virtual_memory_sites.move(&allocation_sites); 2.111 return true; 2.112 } 2.113 2.114 MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) { 2.115 - assert(!_malloc_sites.is_empty(), "Detail baseline?"); 2.116 + assert(!_malloc_sites.is_empty(), "Not detail baseline"); 2.117 switch(order) { 2.118 case by_size: 2.119 malloc_sites_to_size_order(); 2.120 @@ -251,7 +233,7 @@ 2.121 } 2.122 2.123 VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) { 2.124 - assert(!_virtual_memory_sites.is_empty(), "Detail baseline?"); 2.125 + assert(!_virtual_memory_sites.is_empty(), "Not detail baseline"); 2.126 switch(order) { 2.127 case by_size: 2.128 virtual_memory_sites_to_size_order(); 2.129 @@ -270,8 +252,7 @@ 2.130 // Sorting allocations sites in different orders 2.131 void MemBaseline::malloc_sites_to_size_order() { 2.132 if (_malloc_sites_order != by_size) { 2.133 - SortedLinkedList<MallocSite, compare_malloc_size, ResourceObj::ARENA> 2.134 - tmp(arena()); 2.135 + SortedLinkedList<MallocSite, compare_malloc_size> tmp; 2.136 2.137 // Add malloc sites to sorted linked list to sort into size order 2.138 tmp.move(&_malloc_sites); 2.139 @@ -283,8 +264,7 @@ 2.140 2.141 void MemBaseline::malloc_sites_to_allocation_site_order() { 2.142 if (_malloc_sites_order != by_site) { 2.143 - SortedLinkedList<MallocSite, compare_malloc_site, ResourceObj::ARENA> 2.144 - tmp(arena()); 2.145 + SortedLinkedList<MallocSite, compare_malloc_site> tmp; 2.146 // Add malloc sites to sorted linked list to sort into site (address) order 2.147 tmp.move(&_malloc_sites); 2.148 _malloc_sites.set_head(tmp.head()); 2.149 @@ -295,8 +275,7 @@ 2.150 2.151 void MemBaseline::virtual_memory_sites_to_size_order() { 2.152 if (_virtual_memory_sites_order != by_size) { 2.153 - SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size, ResourceObj::ARENA> 2.154 - tmp(arena()); 2.155 + SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp; 2.156 2.157 tmp.move(&_virtual_memory_sites); 2.158 2.159 @@ -308,10 +287,9 @@ 2.160 2.161 void MemBaseline::virtual_memory_sites_to_reservation_site_order() { 2.162 if (_virtual_memory_sites_order != by_size) { 2.163 - SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site, ResourceObj::ARENA> 2.164 - tmp(arena()); 2.165 + SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp; 2.166 2.167 - tmp.add(&_virtual_memory_sites); 2.168 + tmp.move(&_virtual_memory_sites); 2.169 2.170 _virtual_memory_sites.set_head(tmp.head()); 2.171 tmp.set_head(NULL);
3.1 --- a/src/share/vm/services/memBaseline.hpp Tue Aug 19 09:05:55 2014 -0400 3.2 +++ b/src/share/vm/services/memBaseline.hpp Wed Aug 20 08:41:15 2014 -0400 3.3 @@ -61,28 +61,22 @@ 3.4 }; 3.5 3.6 private: 3.7 - // All baseline data is stored in this arena 3.8 - Arena* _arena; 3.9 - 3.10 // Summary information 3.11 - MallocMemorySnapshot* _malloc_memory_snapshot; 3.12 - VirtualMemorySnapshot* _virtual_memory_snapshot; 3.13 + MallocMemorySnapshot _malloc_memory_snapshot; 3.14 + VirtualMemorySnapshot _virtual_memory_snapshot; 3.15 3.16 size_t _class_count; 3.17 3.18 // Allocation sites information 3.19 // Malloc allocation sites 3.20 - LinkedListImpl<MallocSite, ResourceObj::ARENA> 3.21 - _malloc_sites; 3.22 + LinkedListImpl<MallocSite> _malloc_sites; 3.23 3.24 // All virtual memory allocations 3.25 - LinkedListImpl<ReservedMemoryRegion, ResourceObj::ARENA> 3.26 - _virtual_memory_allocations; 3.27 + LinkedListImpl<ReservedMemoryRegion> _virtual_memory_allocations; 3.28 3.29 // Virtual memory allocations by allocation sites, always in by_address 3.30 // order 3.31 - LinkedListImpl<VirtualMemoryAllocationSite, ResourceObj::ARENA> 3.32 - _virtual_memory_sites; 3.33 + LinkedListImpl<VirtualMemoryAllocationSite> _virtual_memory_sites; 3.34 3.35 SortingOrder _malloc_sites_order; 3.36 SortingOrder _virtual_memory_sites_order; 3.37 @@ -93,30 +87,23 @@ 3.38 // create a memory baseline 3.39 MemBaseline(): 3.40 _baseline_type(Not_baselined), 3.41 - _class_count(0), 3.42 - _arena(NULL), 3.43 - _malloc_memory_snapshot(NULL), 3.44 - _virtual_memory_snapshot(NULL), 3.45 - _malloc_sites(NULL) { 3.46 + _class_count(0) { 3.47 } 3.48 3.49 ~MemBaseline() { 3.50 reset(); 3.51 - if (_arena != NULL) { 3.52 - delete _arena; 3.53 - } 3.54 } 3.55 3.56 bool baseline(bool summaryOnly = true); 3.57 3.58 BaselineType baseline_type() const { return _baseline_type; } 3.59 3.60 - MallocMemorySnapshot* malloc_memory_snapshot() const { 3.61 - return _malloc_memory_snapshot; 3.62 + MallocMemorySnapshot* malloc_memory_snapshot() { 3.63 + return &_malloc_memory_snapshot; 3.64 } 3.65 3.66 - VirtualMemorySnapshot* virtual_memory_snapshot() const { 3.67 - return _virtual_memory_snapshot; 3.68 + VirtualMemorySnapshot* virtual_memory_snapshot() { 3.69 + return &_virtual_memory_snapshot; 3.70 } 3.71 3.72 MallocSiteIterator malloc_sites(SortingOrder order); 3.73 @@ -133,10 +120,8 @@ 3.74 // memory 3.75 size_t total_reserved_memory() const { 3.76 assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.77 - assert(_virtual_memory_snapshot != NULL, "No virtual memory snapshot"); 3.78 - assert(_malloc_memory_snapshot != NULL, "No malloc memory snapshot"); 3.79 - size_t amount = _malloc_memory_snapshot->total() + 3.80 - _virtual_memory_snapshot->total_reserved(); 3.81 + size_t amount = _malloc_memory_snapshot.total() + 3.82 + _virtual_memory_snapshot.total_reserved(); 3.83 return amount; 3.84 } 3.85 3.86 @@ -144,32 +129,30 @@ 3.87 // virtual memory 3.88 size_t total_committed_memory() const { 3.89 assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.90 - assert(_virtual_memory_snapshot != NULL, 3.91 - "Not a snapshot"); 3.92 - size_t amount = _malloc_memory_snapshot->total() + 3.93 - _virtual_memory_snapshot->total_committed(); 3.94 + size_t amount = _malloc_memory_snapshot.total() + 3.95 + _virtual_memory_snapshot.total_committed(); 3.96 return amount; 3.97 } 3.98 3.99 size_t total_arena_memory() const { 3.100 assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.101 - assert(_malloc_memory_snapshot != NULL, "Not yet baselined"); 3.102 - return _malloc_memory_snapshot->total_arena(); 3.103 + return _malloc_memory_snapshot.total_arena(); 3.104 } 3.105 3.106 size_t malloc_tracking_overhead() const { 3.107 assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.108 - return _malloc_memory_snapshot->malloc_overhead()->size(); 3.109 + MemBaseline* bl = const_cast<MemBaseline*>(this); 3.110 + return bl->_malloc_memory_snapshot.malloc_overhead()->size(); 3.111 } 3.112 3.113 - const MallocMemory* malloc_memory(MEMFLAGS flag) const { 3.114 - assert(_malloc_memory_snapshot != NULL, "Not a snapshot"); 3.115 - return _malloc_memory_snapshot->by_type(flag); 3.116 + MallocMemory* malloc_memory(MEMFLAGS flag) { 3.117 + assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.118 + return _malloc_memory_snapshot.by_type(flag); 3.119 } 3.120 3.121 - const VirtualMemory* virtual_memory(MEMFLAGS flag) const { 3.122 - assert(_virtual_memory_snapshot != NULL, "Not a snapshot"); 3.123 - return _virtual_memory_snapshot->by_type(flag); 3.124 + VirtualMemory* virtual_memory(MEMFLAGS flag) { 3.125 + assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.126 + return _virtual_memory_snapshot.by_type(flag); 3.127 } 3.128 3.129 3.130 @@ -180,24 +163,19 @@ 3.131 3.132 size_t thread_count() const { 3.133 assert(baseline_type() != Not_baselined, "Not yet baselined"); 3.134 - assert(_malloc_memory_snapshot != NULL, "Baselined?"); 3.135 - return _malloc_memory_snapshot->thread_count(); 3.136 + return _malloc_memory_snapshot.thread_count(); 3.137 } 3.138 3.139 // reset the baseline for reuse 3.140 void reset() { 3.141 _baseline_type = Not_baselined; 3.142 - _malloc_memory_snapshot = NULL; 3.143 - _virtual_memory_snapshot = NULL; 3.144 + _malloc_memory_snapshot.reset(); 3.145 + _virtual_memory_snapshot.reset(); 3.146 _class_count = 0; 3.147 3.148 - _malloc_sites = NULL; 3.149 - _virtual_memory_sites = NULL; 3.150 - _virtual_memory_allocations = NULL; 3.151 - 3.152 - if (_arena != NULL) { 3.153 - _arena->destruct_contents(); 3.154 - } 3.155 + _malloc_sites.clear(); 3.156 + _virtual_memory_sites.clear(); 3.157 + _virtual_memory_allocations.clear(); 3.158 } 3.159 3.160 private: 3.161 @@ -210,8 +188,6 @@ 3.162 // Aggregate virtual memory allocation by allocation sites 3.163 bool aggregate_virtual_memory_allocation_sites(); 3.164 3.165 - Arena* arena() { return _arena; } 3.166 - 3.167 // Sorting allocation sites in different orders 3.168 // Sort allocation sites in size order 3.169 void malloc_sites_to_size_order();