changeset 75:7e8c6ccee74d

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:49:47 +0900
parents b6ea4d40d35f
children 39b7535558bc
files agent/ChangeLog agent/src/oopUtil.hpp agent/src/snapShotMain.cpp
diffstat 3 files changed, 36 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ChangeLog	Fri Mar 10 13:40:42 2017 +0900
+++ b/agent/ChangeLog	Thu Jun 08 23:49:47 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-03-10 KUBOTA Yuji <kubota.yuji@lab.ntt.co.jp>
 
 	* Bump to 1.0.7
--- a/agent/src/oopUtil.hpp	Fri Mar 10 13:40:42 2017 +0900
+++ b/agent/src/oopUtil.hpp	Thu Jun 08 23:49:47 2017 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file oopUtil.hpp
  * \brief This file is used to getting information inner JVM.<br>
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -203,6 +203,13 @@
  */
 extern "C" int *safePointState;
 
+/*!
+ * \brief Numbering which shows safepoint state as enumeration.
+ */
+#define SAFEPOINT_STATE_NORMAL_EXECUTION 0
+#define SAFEPOINT_STATE_SYNCHRONIZING    1
+#define SAFEPOINT_STATE_SYNCHRONIZED     2
+
 /* Define CMS GC pointer variable for calling from external. */
 
 /* Define function pointer variable for calling from external. */
@@ -533,7 +540,15 @@
  * \return Is synchronizing or working at safepoint now.
  */
 inline bool isAtSafepoint(void) {
-  return (*safePointState == 2);
+    return (*safePointState == SAFEPOINT_STATE_SYNCHRONIZED);
+}
+
+/*!
+ * \brief Get safepoint state.
+ * \return Is not at safepoint now.
+ */
+inline bool isAtNormalExecution(void) {
+    return (*safePointState == SAFEPOINT_STATE_NORMAL_EXECUTION);
 }
 
 /*!
--- a/agent/src/snapShotMain.cpp	Fri Mar 10 13:40:42 2017 +0900
+++ b/agent/src/snapShotMain.cpp	Thu Jun 08 23:49:47 2017 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file snapShotMain.cpp
  * \brief This file is used to take snapshot.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2017 Nippon Telegraph and Telephone Corporation
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,6 +27,7 @@
 
 #include <execinfo.h>
 #include <pthread.h>
+#include <sched.h>
 
 #include "snapShotMain.hpp"
 #include "libmain.hpp"
@@ -132,6 +133,14 @@
 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 = asKlassOop(mirror);
@@ -153,6 +162,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 = asKlassOop(mirror);