# HG changeset patch # User KUBOTA Yuji # Date 1496930810 -32400 # Node ID b862390b22bce8b5693c58df2eda1c1ddf44a635 # Parent 5e09d5bd2a1713620cda0c4d3b91bd0913380751 Bug 3399: Fix potential error when conflict between class loading and GC Reviewed-by: yasuenag https://github.com/HeapStats/heapstats/pull/99 diff -r 5e09d5bd2a17 -r b862390b22bc ChangeLog --- a/ChangeLog Fri May 12 23:26:25 2017 +0900 +++ b/ChangeLog Thu Jun 08 23:06:50 2017 +0900 @@ -1,3 +1,7 @@ +2017-06-08 KUBOTA Yuji + + * Bug 3399: Fix potential error when conflict between class loading and GC + 2017-05-12 Yasumasa Suenaga * Bug 3382: Class Search window is too narrow diff -r 5e09d5bd2a17 -r b862390b22bc agent/src/heapstats-engines/classContainer.cpp --- a/agent/src/heapstats-engines/classContainer.cpp Fri May 12 23:26:25 2017 +0900 +++ b/agent/src/heapstats-engines/classContainer.cpp Thu Jun 08 23:06:50 2017 +0900 @@ -905,6 +905,11 @@ */ void JNICALL OnClassUnload(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) { + /* + * This function does not require to check whether at safepoint because + * Class Unloading always executes at safepoint. + */ + /* Get klassOop. */ void *mirror = *(void **)klass; void *klassOop = TVMFunctions::getInstance()->AsKlassOop(mirror); diff -r 5e09d5bd2a17 -r b862390b22bc agent/src/heapstats-engines/deadlockFinder.cpp --- a/agent/src/heapstats-engines/deadlockFinder.cpp Fri May 12 23:26:25 2017 +0900 +++ b/agent/src/heapstats-engines/deadlockFinder.cpp Thu Jun 08 23:06:50 2017 +0900 @@ -62,16 +62,6 @@ TDeadlockFinder *TDeadlockFinder::inst = NULL; -/* Common methods. */ - -/*! - * \brief Get safepoint state. - * \return Is synchronizing or working at safepoint now. - */ -inline bool isAtSafepoint(void) { - return (TVMVariables::getInstance()->getSafePointState() == 2); -} - /*! * \brief Event handler of JVMTI MonitorContendedEnter for finding deadlock. * \param jvmti [in] JVMTI environment. diff -r 5e09d5bd2a17 -r b862390b22bc agent/src/heapstats-engines/snapShotMain.cpp --- a/agent/src/heapstats-engines/snapShotMain.cpp Fri May 12 23:26:25 2017 +0900 +++ b/agent/src/heapstats-engines/snapShotMain.cpp Thu Jun 08 23:06:50 2017 +0900 @@ -19,6 +19,8 @@ * */ +#include + #include "globals.hpp" #include "vmFunctions.hpp" #include "elapsedTimer.hpp" @@ -135,6 +137,15 @@ */ void JNICALL OnClassPrepare(jvmtiEnv *jvmti, JNIEnv *env, jthread thread, jclass klass) { + + /* + * Wait if VM is at a safepoint which includes safepoint synchronizing, + * because jclass (oop in JNIHandle) might be relocated. + */ + while (!isAtNormalExecution()) { + sched_yield(); + } + /* Get klassOop. */ void *mirror = *(void **)klass; void *klassOop = TVMFunctions::getInstance()->AsKlassOop(mirror); diff -r 5e09d5bd2a17 -r b862390b22bc agent/src/heapstats-engines/vmVariables.hpp --- a/agent/src/heapstats-engines/vmVariables.hpp Fri May 12 23:26:25 2017 +0900 +++ b/agent/src/heapstats-engines/vmVariables.hpp Thu Jun 08 23:06:50 2017 +0900 @@ -1,7 +1,7 @@ /*! * \file vmVariables.hpp * \brief This file includes variables in HotSpot VM. - * Copyright (C) 2014-2016 Yasumasa Suenaga + * Copyright (C) 2014-2017 Yasumasa Suenaga * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -36,6 +36,12 @@ */ #define SAFEPOINT_STATE_SYMBOL "_ZN20SafepointSynchronize6_stateE" +/*! + * \brief Numbering which shows safepoint state as enumeration. + */ +#define SAFEPOINT_STATE_NORMAL_EXECUTION 0 +#define SAFEPOINT_STATE_SYNCHRONIZING 1 +#define SAFEPOINT_STATE_SYNCHRONIZED 2 /* extern variables */ extern "C" void *collectedHeap; @@ -467,4 +473,24 @@ inline size_t getYoungGenSize() const { return youngGenSize; }; }; +/* Utility functions for Safepoint */ + +/*! + * \brief Check whether VM is at safepoint or not. + * \return true if VM is at safepoint. + */ +inline bool isAtSafepoint(void) { + return (TVMVariables::getInstance()->getSafePointState() + == SAFEPOINT_STATE_SYNCHRONIZED); +}; + +/*! + * \brief Check whether VM is at normal execution or not. + * \return true if VM is at normal execution. + */ +inline bool isAtNormalExecution(void) { + return (TVMVariables::getInstance()->getSafePointState() + == SAFEPOINT_STATE_NORMAL_EXECUTION); +}; + #endif // VMVARIABLES_H