--- old/src/hotspot/share/runtime/perfMemory.cpp 2017-10-19 20:39:32.581905099 +0900 +++ new/src/hotspot/share/runtime/perfMemory.cpp 2017-10-19 20:39:32.248931915 +0900 @@ -53,6 +53,7 @@ size_t PerfMemory::_capacity = 0; jint PerfMemory::_initialized = false; PerfDataPrologue* PerfMemory::_prologue = NULL; +bool PerfMemory::_destroyed = false; void perfMemory_init() { @@ -64,7 +65,7 @@ void perfMemory_exit() { if (!UsePerfData) return; - if (!PerfMemory::is_initialized()) return; + if (!PerfMemory::is_usable()) return; // Only destroy PerfData objects if we're at a safepoint and the // StatSampler is not active. Otherwise, we risk removing PerfData @@ -88,7 +89,7 @@ void PerfMemory::initialize() { - if (_prologue != NULL) + if (is_initialized()) // initialization already performed return; @@ -160,7 +161,7 @@ void PerfMemory::destroy() { - if (_prologue == NULL) return; + if (!is_usable()) return; if (_start != NULL && _prologue->overflow != 0) { @@ -196,11 +197,7 @@ delete_memory_region(); } - _start = NULL; - _end = NULL; - _top = NULL; - _prologue = NULL; - _capacity = 0; + _destroyed = true; } // allocate an aligned block of memory from the PerfData memory @@ -213,7 +210,7 @@ MutexLocker ml(PerfDataMemAlloc_lock); - assert(_prologue != NULL, "called before initialization"); + assert(is_usable(), "called before init or after destroy"); // check that there is enough memory for this request if ((_top + size) >= _end) { @@ -238,6 +235,8 @@ void PerfMemory::mark_updated() { if (!UsePerfData) return; + assert(is_usable(), "called before init or after destroy"); + _prologue->mod_time_stamp = os::elapsed_counter(); } --- old/src/hotspot/share/runtime/perfMemory.hpp 2017-10-19 20:39:33.338844140 +0900 +++ new/src/hotspot/share/runtime/perfMemory.hpp 2017-10-19 20:39:33.105862903 +0900 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,6 +113,7 @@ */ class PerfMemory : AllStatic { friend class VMStructs; + friend class PerfMemoryTest; private: static char* _start; static char* _end; @@ -120,6 +121,7 @@ static size_t _capacity; static PerfDataPrologue* _prologue; static jint _initialized; + static bool _destroyed; static void create_memory_region(size_t sizep); static void delete_memory_region(); @@ -136,6 +138,8 @@ static size_t used() { return (size_t) (_top - _start); } static size_t capacity() { return _capacity; } static bool is_initialized() { return _initialized != 0; } + static bool is_destroyed() { return _destroyed; } + static bool is_usable() { return is_initialized() && !is_destroyed(); } static bool contains(char* addr) { return ((_start != NULL) && (addr >= _start) && (addr < _end)); } --- /dev/null 2017-10-19 20:28:20.278443400 +0900 +++ new/test/hotspot/gtest/runtime/test_perfdata.cpp 2017-10-19 20:39:33.706814506 +0900 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "unittest.hpp" + +class PerfMemoryTest : public ::testing::Test { + public: + static char* top() { return PerfMemory::_top; } + static PerfDataPrologue* prologue() { return PerfMemory::_prologue; } +}; + +TEST_VM_F(PerfMemoryTest, destroy) { + PerfMemory::destroy(); + + ASSERT_NE(PerfMemory::start(), (char*)NULL) << "PerfMemory::_start should not be NULL"; + ASSERT_NE(PerfMemory::end(), (char*)NULL) << "PerfMemory::_end should not be NULL"; + ASSERT_NE(PerfMemoryTest::top(), (char*)NULL) << "PerfMemory::_top should not be NULL"; + ASSERT_NE(PerfMemoryTest::prologue(), (PerfDataPrologue*)NULL) << "PerfMemory::_prologue should not be NULL"; + ASSERT_NE(PerfMemory::capacity(), (size_t)0) << "PerfMemory::_capacity should not be 0"; +} +