changeset 232:b862390b22bc

Bug 3399: Fix potential error when conflict between class loading and GC Reviewed-by: yasuenag https://github.com/HeapStats/heapstats/pull/99
author KUBOTA Yuji <kubota.yuji@lab.ntt.co.jp>
date Thu, 08 Jun 2017 23:06:50 +0900
parents 5e09d5bd2a17
children 1ac3803a35d1
files ChangeLog agent/src/heapstats-engines/classContainer.cpp agent/src/heapstats-engines/deadlockFinder.cpp agent/src/heapstats-engines/snapShotMain.cpp agent/src/heapstats-engines/vmVariables.hpp
diffstat 5 files changed, 47 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- 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 <kubota.yuji@lab.ntt.co.jp>
+
+	* Bug 3399: Fix potential error when conflict between class loading and GC
+
 2017-05-12  Yasumasa Suenaga <yasuenag@gmail.com>
 
 	* Bug 3382: Class Search window is too narrow
--- 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);
--- 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.
--- 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 <sched.h>
+
 #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);
--- 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