From 4c7d14c1205242a357a5c436fdd78113e7e028da Mon Sep 17 00:00:00 2001 From: zgu Date: Thu, 14 Aug 2014 09:02:51 -0400 Subject: [PATCH] 8054368: nsk/jdi/VirtualMachine/exit/exit002 crash with detail tracking on (NMT2) Summary: Dynamic allocate _reserved_regions instead of static object to avoid racing during process exit Reviewed-by: dholmes, coleenp --- src/share/vm/services/memTracker.cpp | 7 ++- .../vm/services/virtualMemoryTracker.cpp | 43 +++++++++++++------ .../vm/services/virtualMemoryTracker.hpp | 5 ++- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/share/vm/services/memTracker.cpp b/src/share/vm/services/memTracker.cpp index 6a36163cc..dac2c2b8f 100644 --- a/src/share/vm/services/memTracker.cpp +++ b/src/share/vm/services/memTracker.cpp @@ -77,7 +77,12 @@ NMT_TrackingLevel MemTracker::init_tracking_level() { } void MemTracker::init() { - if (tracking_level() >= NMT_summary) { + NMT_TrackingLevel level = tracking_level(); + if (level >= NMT_summary) { + if (!VirtualMemoryTracker::late_initialize(level)) { + shutdown(); + return; + } _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock"); // Already OOM. It is unlikely, but still have to handle it. if (_query_lock == NULL) { diff --git a/src/share/vm/services/virtualMemoryTracker.cpp b/src/share/vm/services/virtualMemoryTracker.cpp index 4e0476f90..4a6e20ab6 100644 --- a/src/share/vm/services/virtualMemoryTracker.cpp +++ b/src/share/vm/services/virtualMemoryTracker.cpp @@ -34,7 +34,7 @@ void VirtualMemorySummary::initialize() { ::new ((void*)_snapshot) VirtualMemorySnapshot(); } -SortedLinkedList VirtualMemoryTracker::_reserved_regions; +SortedLinkedList* VirtualMemoryTracker::_reserved_regions; int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) { return r1.compare(r2); @@ -283,17 +283,26 @@ bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { return true; } +bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) { + if (level >= NMT_summary) { + _reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT) + SortedLinkedList(); + return (_reserved_regions != NULL); + } + return true; +} + bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) { assert(base_addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); - + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(base_addr, size, stack, flag); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); LinkedListNode* node; if (reserved_rgn == NULL) { VirtualMemorySummary::record_reserved_memory(size, flag); - node = _reserved_regions.add(rgn); + node = _reserved_regions->add(rgn); if (node != NULL) { node->data()->set_all_committed(all_committed); return true; @@ -338,9 +347,10 @@ bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) { assert(addr != NULL, "Invalid address"); + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(addr, 1); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); if (reserved_rgn != NULL) { assert(reserved_rgn->contain_address(addr), "Containment"); if (reserved_rgn->flag() != flag) { @@ -354,8 +364,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, const NativeCallStack& stack) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); + ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); @@ -365,8 +377,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); + ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); return reserved_rgn->remove_uncommitted_region(addr, size); @@ -375,9 +389,10 @@ bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { assert(addr != NULL, "Invalid address"); assert(size > 0, "Invalid size"); + assert(_reserved_regions != NULL, "Sanity check"); ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn); + ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); assert(reserved_rgn != NULL, "No reserved region"); @@ -390,7 +405,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag()); if (reserved_rgn->same_region(addr, size)) { - return _reserved_regions.remove(rgn); + return _reserved_regions->remove(rgn); } else { assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); if (reserved_rgn->base() == addr || @@ -405,7 +420,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { // use original region for lower region reserved_rgn->exclude_region(addr, top - addr); - LinkedListNode* new_rgn = _reserved_regions.add(high_rgn); + LinkedListNode* new_rgn = _reserved_regions->add(high_rgn); if (new_rgn == NULL) { return false; } else { @@ -418,8 +433,9 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { + assert(_reserved_regions != NULL, "Sanity check"); ThreadCritical tc; - LinkedListNode* head = _reserved_regions.head(); + LinkedListNode* head = _reserved_regions->head(); while (head != NULL) { const ReservedMemoryRegion* rgn = head->peek(); if (!walker->do_allocation_site(rgn)) { @@ -439,7 +455,10 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel assert(from == NMT_summary || from == NMT_detail, "Just check"); // Clean up virtual memory tracking data structures. ThreadCritical tc; - _reserved_regions.clear(); + if (_reserved_regions != NULL) { + delete _reserved_regions; + _reserved_regions = NULL; + } } return true; diff --git a/src/share/vm/services/virtualMemoryTracker.hpp b/src/share/vm/services/virtualMemoryTracker.hpp index 982b1531f..8d29a66f2 100644 --- a/src/share/vm/services/virtualMemoryTracker.hpp +++ b/src/share/vm/services/virtualMemoryTracker.hpp @@ -414,6 +414,9 @@ class VirtualMemoryTracker : AllStatic { public: static bool initialize(NMT_TrackingLevel level); + // Late phase initialization + static bool late_initialize(NMT_TrackingLevel level); + static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MEMFLAGS flag = mtNone, bool all_committed = false); @@ -428,7 +431,7 @@ class VirtualMemoryTracker : AllStatic { static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to); private: - static SortedLinkedList _reserved_regions; + static SortedLinkedList* _reserved_regions; }; -- GitLab