changeset 70:79f42583c31c

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:48:52 +0900
parents 60be2921a8bf
children 58527d62409a
files agent/ChangeLog agent/src/classContainer.cpp agent/src/oopUtil.hpp agent/src/snapShotMain.cpp
diffstat 4 files changed, 35 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/agent/ChangeLog	Fri Mar 10 13:41:27 2017 +0900
+++ b/agent/ChangeLog	Thu Jun 08 23:48:52 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.1.6
--- a/agent/src/classContainer.cpp	Fri Mar 10 13:41:27 2017 +0900
+++ b/agent/src/classContainer.cpp	Thu Jun 08 23:48:52 2017 +0900
@@ -957,6 +957,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);
--- a/agent/src/oopUtil.hpp	Fri Mar 10 13:41:27 2017 +0900
+++ b/agent/src/oopUtil.hpp	Thu Jun 08 23:48:52 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
@@ -231,6 +231,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. */
@@ -571,7 +578,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:41:27 2017 +0900
+++ b/agent/src/snapShotMain.cpp	Thu Jun 08 23:48:52 2017 +0900
@@ -27,6 +27,7 @@
 
 #include <execinfo.h>
 #include <pthread.h>
+#include <sched.h>
 
 #include "snapShotMain.hpp"
 #include "libmain.hpp"
@@ -151,6 +152,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);