changeset 157:f3e6f861c1b2

Bug 2911: [REFACTORING][JDK 9] Refactoring signal handling mechanism
author Yasumasa Suenaga <yasuenag@gmail.com>
date Mon, 18 Apr 2016 21:28:04 +0900
parents 6a568c9776c3
children f5626d1b4522
files agent/src/heapstats-engines/configuration.cpp agent/src/heapstats-engines/configuration.hpp agent/src/heapstats-engines/libmain.cpp agent/src/heapstats-engines/logMain.cpp agent/src/heapstats-engines/signalManager.cpp agent/src/heapstats-engines/signalManager.hpp agent/src/heapstats-engines/vmFunctions.cpp agent/src/heapstats-engines/vmFunctions.hpp
diffstat 8 files changed, 304 insertions(+), 653 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/heapstats-engines/configuration.cpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/configuration.cpp	Mon Apr 18 21:28:04 2016 +0900
@@ -21,6 +21,7 @@
 
 #include "globals.hpp"
 #include "fsUtil.hpp"
+#include "signalManager.hpp"
 #include "configuration.hpp"
 
 #if USE_PCRE
@@ -272,7 +273,7 @@
 void TConfiguration::ReadSignalValue(const char *value, char **dest) {
   if (value == NULL) {
     *dest = NULL;
-  } else if (isSupportSignal(value)) {
+  } else if (TSignalManager::findSignal(value) != -1) {
     if (*dest != NULL) {
       free(*dest);
     }
@@ -739,51 +740,6 @@
   }
 }
 
-/*!
- * \brief Check signal is supported by JVM.
- * \param sigName [in] Name of signal.
- * \return Signal is supported, if value is true.
- *         Otherwise, value is false.
- * \sa Please see below JDK source about JVM supported signal.<br>
- *     hotspot/src/os/linux/vm/jvm_linux.cpp
- */
-bool TConfiguration::isSupportSignal(char const *sigName) {
-  /* JVM supported signals. */
-  const char *supportSignals[] = {
-      /* POSIX signal. */
-      "SIGHUP",    "SIGINT",  "SIGQUIT", "SIGILL",  "SIGABRT",  "SIGFPE",
-      "SIGKILL",   "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",  "SIGUSR1",
-      "SIGUSR2",   "SIGCHLD", "SIGCONT", "SIGSTOP", "SIGTSTP",  "SIGTTIN",
-      "SIGTTOU",   "SIGBUS",  "SIGPOLL", "SIGTRAP", "SIGURG",   "SIGVTALRM",
-      "SIGXCPU",   "SIGXFSZ", "SIGPROF",
-
-#ifdef SIGSYS
-      "SIGSYS",
-#endif
-
-      /* Non-POSIX signal. */
-      "SIGIOT",    "SIGIO",   "SIGCLD",  "SIGPWR",  "SIGWINCH",
-#ifdef SIGSTKFLT
-      "SIGSTKFLT",
-#endif
-
-      /* End flag. */
-      NULL
-      /* JVM was not supported below signal. */
-      /* "SIGINFO", "SIGLOST", "SIGEMT", "SIGUNUSED" and etc.. */
-  };
-
-  /* Search signal name. */
-  for (int sigIdx = 0; supportSignals[sigIdx] != NULL; sigIdx++) {
-    if (strcmp(sigName, supportSignals[sigIdx]) == 0) {
-      /* Found. */
-      return true;
-    }
-  }
-
-  return false;
-}
-
 void TConfiguration::setLogLevel(TConfiguration *inst,
                                  TLogLevel val, TLogLevel *dest) {
   *dest = val;
--- a/agent/src/heapstats-engines/configuration.hpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/configuration.hpp	Mon Apr 18 21:28:04 2016 +0900
@@ -323,16 +323,6 @@
 
  protected:
   /*!
-   * \brief Check signal is supported by JVM.
-   * \param sigName [in] Name of signal.
-   * \return Signal is supported, if value is true.
-   *         Otherwise, value is false.
-   * \sa Please see below JDK source about JVM supported signal.<br>
-   *     hotspot/src/os/linux/vm/jvm_linux.cpp
-   */
-  bool isSupportSignal(char const *sigName);
-
-  /*!
    * \brief Read string value from configuration.
    * \param value [in] Value of this configuration.
    * \param dest [in] [out] Destination of this configuration.
--- a/agent/src/heapstats-engines/libmain.cpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/libmain.cpp	Mon Apr 18 21:28:04 2016 +0900
@@ -2,7 +2,7 @@
  * \file libmain.cpp
  * \brief This file is used to common works.<br>
  *        e.g. initialization, finalization, etc...
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2016 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
@@ -105,7 +105,7 @@
  * \param siginfo [in] Information of received signal.
  * \param data    [in] Data of received signal.
  */
-void ReloadSigProc(int signo, void *siginfo, void *data) {
+void ReloadSigProc(int signo, siginfo_t *siginfo, void *data) {
   /* Enable flag. */
   flagReloadConfig = 1;
   NOTIFY_CATCH_SIGNAL;
@@ -265,36 +265,24 @@
     conf->validate();
   }
 
-  /* If failure signal initialization. */
-  if (unlikely(!TSignalManager::globalInitialize(env))) {
-    logger->printWarnMsg("Failure signal handler initialization.");
-    /* Disable many signal. */
-    conf->TriggerOnLogSignal()->set(false);
-    conf->ReloadSignal()->set(NULL);
-  }
-
   /* Initialize signal flag. */
   flagReloadConfig = 0;
 
   /* Start HeapStats agent threads. */
-  try {
-    reloadSigMngr = new TSignalManager(env, &ReloadSigProc);
-
-    /* Switch reload signal state. */
-    if (conf->ReloadSignal()->get() != NULL) {
-      /* Setting new reload signal. */
-      if (unlikely(
-              !reloadSigMngr->catchSignal(env, conf->ReloadSignal()->get()))) {
-        /* Reload configuration signal is disable. */
-        logger->printWarnMsg("Failure register reload configuration signal.");
+  if (conf->ReloadSignal()->get() != NULL) {
+    try {
+      reloadSigMngr = new TSignalManager(conf->ReloadSignal()->get());
+      if (!reloadSigMngr->addHandler(&ReloadSigProc)) {
+        logger->printWarnMsg("Reload signal handler setup is failed.");
         conf->ReloadSignal()->set(NULL);
       }
+    } catch (const char *errMsg) {
+      logger->printWarnMsg(errMsg);
+      conf->ReloadSignal()->set(NULL);
+    } catch (...) {
+      logger->printWarnMsg("Reload signal handler setup is failed.");
+      conf->ReloadSignal()->set(NULL);
     }
-
-  } catch (const char *errMsg) {
-    logger->printWarnMsg(errMsg);
-  } catch (...) {
-    logger->printWarnMsg("AgentThread start failed!");
   }
 
   /* Calculate alert limit. */
@@ -389,11 +377,6 @@
 
   /* If reload log signal is enabled. */
   if (likely(reloadSigMngr != NULL)) {
-    /* Terminate reload signal manager. */
-    if (likely(conf->ReloadSignal()->get() != NULL)) {
-      reloadSigMngr->ignoreSignal(env, conf->ReloadSignal()->get());
-    }
-    reloadSigMngr->terminate(env);
     delete reloadSigMngr;
     reloadSigMngr = NULL;
   }
@@ -413,9 +396,6 @@
                                 conf->ThreadRecordFileName()->get());
     }
   }
-
-  /* Signal finalization. */
-  TSignalManager::globalFinalize(env);
 }
 
 /*!
--- a/agent/src/heapstats-engines/logMain.cpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/logMain.cpp	Mon Apr 18 21:28:04 2016 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file logmain.cpp
  * \brief This file is used common logging process.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2016 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
@@ -108,7 +108,7 @@
  * \param siginfo [in] Information of received signal.
  * \param data    [in] Data of received signal.
  */
-void normalLogProc(int signo, void *siginfo, void *data) {
+void normalLogProc(int signo, siginfo_t *siginfo, void *data) {
   /* Enable flag. */
   flagLogSignal = 1;
   NOTIFY_CATCH_SIGNAL;
@@ -120,7 +120,7 @@
  * \param siginfo [in] Information of received signal.
  * \param data    [in] Data of received signal.
  */
-void anotherLogProc(int signo, void *siginfo, void *data) {
+void anotherLogProc(int signo, siginfo_t *siginfo, void *data) {
   /* Enable flag. */
   flagAllLogSignal = 1;
   NOTIFY_CATCH_SIGNAL;
@@ -365,45 +365,37 @@
   flagLogSignal = 0;
   flagAllLogSignal = 0;
 
-  /* Signal enable flag. */
-  bool enableNormalSig = (conf->LogSignalNormal()->get() != NULL);
-  bool enableAllSig = (conf->LogSignalAll()->get() != NULL);
-
-  try {
-    /* Create instance for log signal. */
-    logSignalMngr = new TSignalManager(env, &normalLogProc);
-    logAllSignalMngr = new TSignalManager(env, &anotherLogProc);
-
-    if (conf->TriggerOnLogSignal()->get()) {
-      /* If "normal log signal" is designated. */
-      if (enableNormalSig) {
-        /* Enable signal handling. */
-        if (unlikely(!logSignalMngr->catchSignal(
-                env, conf->LogSignalNormal()->get()))) {
-          logger->printWarnMsg("Failure register normal log signal.");
-          /* Normal log signal is disable. */
-          conf->LogSignalNormal()->set(NULL);
-        }
+  /* Signal handler setup */
+  if (conf->LogSignalNormal()->get() != NULL) {
+    try {
+      logSignalMngr = new TSignalManager(conf->LogSignalNormal()->get());
+      if (!logSignalMngr->addHandler(&normalLogProc)) {
+        logger->printWarnMsg("Log normal signal handler setup is failed.");
+        conf->LogSignalNormal()->set(NULL);
       }
+    } catch (const char *errMsg) {
+      logger->printWarnMsg(errMsg);
+      conf->LogSignalNormal()->set(NULL);
+    } catch (...) {
+      logger->printWarnMsg("Log normal signal handler setup is failed.");
+      conf->LogSignalNormal()->set(NULL);
+    }
+  }
 
-      /* If "all log signal" is designated. */
-      if (enableAllSig) {
-        /* Enable signal handling. */
-        if (unlikely(!logAllSignalMngr->catchSignal(
-                env, conf->LogSignalAll()->get()))) {
-          logger->printWarnMsg("Failure register all log signal.");
-          /* All log signal is disable. */
-          conf->LogSignalAll()->set(NULL);
-        }
+  if (conf->LogSignalAll()->get() != NULL) {
+    try {
+      logAllSignalMngr = new TSignalManager(conf->LogSignalAll()->get());
+      if (!logAllSignalMngr->addHandler(&anotherLogProc)) {
+        logger->printWarnMsg("Log all signal handler setup is failed.");
+        conf->LogSignalAll()->set(NULL);
       }
+    } catch (const char *errMsg) {
+      logger->printWarnMsg(errMsg);
+      conf->LogSignalAll()->set(NULL);
+    } catch (...) {
+      logger->printWarnMsg("Log all signal handler setup is failed.");
+      conf->LogSignalAll()->set(NULL);
     }
-  } catch (const char *errMsg) {
-    logger->printWarnMsg(errMsg);
-    conf->TriggerOnLogSignal()->set(false);
-
-  } catch (...) {
-    logger->printWarnMsg("Signal handler start failed!");
-    conf->TriggerOnLogSignal()->set(false);
   }
 }
 
@@ -413,30 +405,13 @@
  * \param env   [in] JNI environment object.
  */
 void onVMDeathForLog(jvmtiEnv *jvmti, JNIEnv *env) {
-  /* Flag of signal enable. */
-  bool enableNormalSig = conf->Attach()->get() &&
-                         conf->TriggerOnLogSignal()->get() &&
-                         (conf->LogSignalNormal()->get() != NULL);
-  bool enableAllSig = conf->Attach()->get() &&
-                      conf->TriggerOnLogSignal()->get() &&
-                      (conf->LogSignalAll()->get() != NULL);
-
-  /* If normal log signal is enabled. */
-  if (likely(logSignalMngr != NULL)) {
-    /* Terminate normal log signal manager. */
-    if (enableNormalSig) {
-      logSignalMngr->ignoreSignal(env, conf->LogSignalNormal()->get());
-    }
-    logSignalMngr->terminate(env);
+  if (logSignalMngr != NULL) {
+    delete logSignalMngr;
+    logSignalMngr = NULL;
   }
-
-  /* If all log signal is enabled. */
-  if (likely(logAllSignalMngr != NULL)) {
-    /* Terminate all log signal manager. */
-    if (enableAllSig) {
-      logAllSignalMngr->ignoreSignal(env, conf->LogSignalAll()->get());
-    }
-    logAllSignalMngr->terminate(env);
+  if (logAllSignalMngr != NULL) {
+    delete logAllSignalMngr;
+    logAllSignalMngr = NULL;
   }
 }
 
--- a/agent/src/heapstats-engines/signalManager.cpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/signalManager.cpp	Mon Apr 18 21:28:04 2016 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file signalManager.cpp
  * \brief This file is used by signal handling.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2016 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
@@ -19,418 +19,137 @@
  *
  */
 
+#include <signal.h>
+
 #include "globals.hpp"
+#include "vmFunctions.hpp"
 #include "signalManager.hpp"
 
-/* Class static variables. */
+
+static TSignalHandlerChain *sighandlers[NSIG] = {0};
 
-/*!
- * \brief Object of "NativeSignalHandler" class information.
- */
-jclass TSignalManager::classNativeHandler = NULL;
-/*!
- * \brief Object of "Signal" class information.
- */
-jclass TSignalManager::classSignal = NULL;
-/*!
- * \brief Object of "String" class information.
- */
-jclass TSignalManager::classString = NULL;
+static TSignalMap signalMap[] = 
+  {
+    {SIGHUP,   "SIGHUP"},  {SIGALRM,   "SIGALRM"},  {SIGUSR1,   "SIGUSR1"},
+    {SIGUSR2,  "SIGUSR2"}, {SIGTSTP,   "SIGTSTP"},  {SIGTTIN,   "SIGTTIN"},
+    {SIGTTOU,  "SIGTTOU"}, {SIGPOLL,   "SIGPOLL"},  {SIGVTALRM, "SIGVTALRM"},
+    {SIGIOT,   "SIGIOT"},  {SIGWINCH,  "SIGWINCH"}
+  };
+
+
+void SignalHandlerStub(int signo, siginfo_t *siginfo, void *data) {
+  TSignalHandlerChain *chain = sighandlers[signo];
+  TVMFunctions *vmFunc = TVMFunctions::getInstance();
 
-/*!
- * \brief Constructor of "NativeSignalHandler" class.
- */
-jmethodID TSignalManager::nativeHandler_init = NULL;
-/*!
- * \brief Constructor of "Signal" class.
- */
-jmethodID TSignalManager::signal_init = NULL;
-/*!
- * \brief Constructor of "String" class.
- */
-jmethodID TSignalManager::string_init = NULL;
-/*!
- * \brief Method "handle" of "Signal" class.
- */
-jmethodID TSignalManager::signal_handle = NULL;
+  while (chain != NULL) {
+    if ((void *)chain->handler == vmFunc->GetSRHandlerPointer()) {
+      /* SR handler should be called in HotSpot Thread context. */
+      if (vmFunc->GetThread() != NULL) {
+        chain->handler(signo, siginfo, data);
+      }
+    } else if (((void *)chain->handler == vmFunc->GetUserHandlerPointer()) &&
+               (signo == SIGHUP)) {
+      // This might SHUTDOWN1_SIGNAL handler which is defined in
+      // java.lang.Terminator . (Unix class)
+      // We should ignore this signal.
 
-/*!
- * \brief Default signal handler.
- */
-jobject TSignalManager::signal_DFL = NULL;
+      // Do nothing.
+    } else if ((void *)chain->handler != SIG_IGN) {
+      chain->handler(signo, siginfo, data);
+    }
 
-/*!
- * \brief Flag of load initialize data.
- */
-bool TSignalManager::loadFlag = false;
+    chain = chain->next;
+  }
+}
+
 
 /* Class methods. */
 
 /*!
- * \brief TSignalManager constructor.
- * \param env  [in] JNI environment object.
- * \param proc [in] Pointer of signal callback.
+ * \brief Find signal number from name.
+ * \param sig Signal name.
+ * \return Signal number. Return -1 if not found.
  */
-TSignalManager::TSignalManager(JNIEnv *env, TSignalHandler proc) {
-  /* If don't loaded data yet. */
-  if (unlikely(!loadFlag)) {
-    throw "Didn't initialize signal handler yet.";
+int TSignalManager::findSignal(const char *sig) {
+  for (size_t idx = 0; idx < (sizeof(signalMap) / sizeof(TSignalMap)); idx++) {
+    if (strcmp(signalMap[idx].name, sig) == 0){
+      return signalMap[idx].sig;
+    }
   }
 
-  /* Create signal handler on JVM. */
-  jobject localSigHandler = env->NewObject(
-      classNativeHandler, nativeHandler_init, (jlong)((ptrdiff_t)proc));
-
-  /* If failure create signal handler. */
-  if (unlikely(localSigHandler == NULL)) {
-    handlePendingException(env);
-    throw "Failure create signal handler.";
-  }
+  return -1;
+}
 
-  /* Get global referrence. */
-  insSignalHandler = env->NewGlobalRef(localSigHandler);
+/*!
+ * \brief TSignalManager constructor.
+ * \param sig Signal string.
+ */
+TSignalManager::TSignalManager(const char *sig) {
+  this->signal = findSignal(sig);
 
-  /* If failure get global referrence. */
-  if (unlikely(insSignalHandler == NULL)) {
-    handlePendingException(env);
-    env->DeleteLocalRef(localSigHandler);
-    throw "Failure create signal handler.";
+  if (this->signal == -1) {
+    static char errstr[1024];
+    snprintf(errstr, 1024, "Invalid signal: %s", sig);
+    throw errstr;
   }
-
-  env->DeleteLocalRef(localSigHandler);
 }
 
 /*!
  * \brief TSignalManager destructor.
  */
-TSignalManager::~TSignalManager(void) { /* None. */ }
-
-/*!
- * \brief Add signal which is handled.
- * \param env     [in] JNI environment object.
- * \param sigName [in] Name of signal.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- */
-bool TSignalManager::catchSignal(JNIEnv *env, char *sigName) {
-  /* Set user's signal handler. */
-  return setSignalHandler(env, sigName, insSignalHandler);
-}
+TSignalManager::~TSignalManager() {
+  TSignalHandlerChain *chain = sighandlers[this->signal];
+  JVM_RegisterSignal(this->signal, (void *)chain->handler);
 
-/*!
- * \brief Specify signal to ignore.
- * \param env     [in] JNI environment object.
- * \param sigName [in] Name of signal.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- */
-bool TSignalManager::ignoreSignal(JNIEnv *env, char *sigName) {
-  /* Set default signal handler. */
-  return setSignalHandler(env, sigName, signal_DFL);
-}
-
-/*!
- * \brief Terminate handling signal.
- * \param env [in] JNI environment object.
- */
-void TSignalManager::terminate(JNIEnv *env) {
-  /* Sanity check. */
-  if (likely(insSignalHandler != NULL)) {
-    /* Delete global reference. */
-    env->DeleteGlobalRef(insSignalHandler);
-    insSignalHandler = NULL;
+  while (chain != NULL) {
+    TSignalHandlerChain *next = chain->next;
+    free(chain);
+    chain = next;
   }
 }
 
 /*!
- * \brief Global initialization.
- * \param env [in] JNI environment object.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- * \warning Please call only once from main thread.
+ * \brief Add signal handler.
+ * \param handler [in] Function pointer for signal handler.
+ * \return true if new signal handler is added.
  */
-bool TSignalManager::globalInitialize(JNIEnv *env) {
-  /* If already loaded data. */
-  if (loadFlag) {
-    logger->printWarnMsg("Already initialized signal manager.");
-    return true;
-  }
-  loadFlag = true;
-
-  /* Search class. */
+bool TSignalManager::addHandler(TSignalHandler handler) {
+  TSignalHandlerChain *chain = sighandlers[this->signal];
 
-  /* Search class list. */
-  struct {
-    jclass *pClass;
-    char className[255];
-    jmethodID *pClassInit;
-    char initArgs[255];
-  } loadClassList[] = {
-        {&classNativeHandler, "Lsun/misc/NativeSignalHandler;",
-         &nativeHandler_init, "(J)V"},
-        {&classSignal, "Lsun/misc/Signal;", &signal_init,
-         "(Ljava/lang/String;)V"},
-        {&classString, "Ljava/lang/String;", &string_init, "([B)V"},
-        {NULL, {0}, NULL, {0}} /* End flag. */
-    };
+  if (chain == NULL) {
+    TSignalHandler oldHandler = (TSignalHandler)JVM_RegisterSignal(
+                                     this->signal, (void *)&SignalHandlerStub);
 
-  /* Search class and get global reference. */
-  for (int i = 0; loadClassList[i].pClass != NULL; i++) {
-    /* Find java class. */
-    jclass localRefClass = env->FindClass(loadClassList[i].className);
-    /* If not found common class. */
-    if (unlikely(localRefClass == NULL)) {
-      handlePendingException(env);
-
-      logger->printWarnMsg("Couldn't get common class.");
+    if ((ptrdiff_t)oldHandler == -1L) { // Cannot set
       return false;
-    }
-
-    /* Get global reference. */
-    (*loadClassList[i].pClass) = (jclass)env->NewGlobalRef(localRefClass);
-    /* If failure getting global reference. */
-    if (unlikely((*loadClassList[i].pClass) == NULL)) {
-      handlePendingException(env);
-
-      logger->printWarnMsg("Couldn't get global reference.");
-      return false;
+    } else if ((ptrdiff_t)oldHandler == 1L) { // Ignore signal
+      oldHandler = (TSignalHandler)SIG_IGN;
+    } else if ((ptrdiff_t)oldHandler == 2L) { // User Handler in HotSpot
+      oldHandler =
+           (TSignalHandler)TVMFunctions::getInstance()->GetUserHandlerPointer();
     }
 
-    /* Get class constructor. */
-    (*loadClassList[i].pClassInit) =
-        env->GetMethodID(localRefClass, "<init>", loadClassList[i].initArgs);
-    /* If failure getting constructor. */
-    if (unlikely((*loadClassList[i].pClassInit) == NULL)) {
-      handlePendingException(env);
+    chain = (TSignalHandlerChain *)calloc(1, sizeof(TSignalHandlerChain));
 
-      logger->printWarnMsg("Couldn't get constructor of common class.");
-      return false;
+    if (chain == NULL) {
+      throw errno;
     }
 
-    /* Clearup. */
-    env->DeleteLocalRef(localRefClass);
-  }
-
-  /* Search method. */
-
-  /* Get "Signal" class "handle" method. */
-  signal_handle = env->GetStaticMethodID(
-      classSignal, "handle",
-      "(Lsun/misc/Signal;Lsun/misc/SignalHandler;)Lsun/misc/SignalHandler;");
-  /* If failure getting "handle" function. */
-  if (unlikely(signal_handle == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't get function of signal handling.");
-    return false;
+    chain->handler = oldHandler;
+    sighandlers[this->signal] = chain;
   }
 
-  /* Search default signal handler. */
-  return getDefaultSignalHandler(env);
-}
-
-/*!
- * \brief Global finalize.
- * \param env [in] JNI environment object.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- * \warning Please call only once from main thread.
- */
-bool TSignalManager::globalFinalize(JNIEnv *env) {
-  /* Sanity check. */
-  if (!loadFlag) {
-    logger->printWarnMsg("Didn't initialize signal manager yet.");
-    return false;
-  }
-  loadFlag = false;
-
-  /* Delete common data's global reference. */
-  if (likely(classNativeHandler != NULL)) {
-    env->DeleteGlobalRef(classNativeHandler);
-    classNativeHandler = NULL;
-  }
-  if (likely(classSignal != NULL)) {
-    env->DeleteGlobalRef(classSignal);
-    classSignal = NULL;
-  }
-  if (likely(classString != NULL)) {
-    env->DeleteGlobalRef(classString);
-    classString = NULL;
-  }
-  if (likely(signal_DFL != NULL)) {
-    env->DeleteGlobalRef(signal_DFL);
-    signal_DFL = NULL;
+  while (chain->next != NULL) {
+    chain = chain->next;
   }
 
+  chain->next = (TSignalHandlerChain *)calloc(1, sizeof(TSignalHandlerChain));
+
+  if (chain->next == NULL) {
+    throw errno;
+  }
+
+  chain->next->handler = handler;
   return true;
 }
 
-/*!
- * \brief Setting signal handle function.
- * \param env     [in] JNI environment object.
- * \param sigName [in] Name of signal.
- * \param handler [in] Setting signal handler.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- */
-bool TSignalManager::setSignalHandler(JNIEnv *env, char *sigName,
-                                      jobject handler) {
-  /* Sanity check. */
-  if (unlikely(insSignalHandler == NULL)) {
-    logger->printWarnMsg("Illegal signal handler.");
-    return false;
-  }
-
-  jobject insSignal = NULL;
-  jobject olderHandler = NULL;
-  jstring javaSigName = NULL;
-
-  /* Create string in java (We should cut SIG from sigName) */
-  if (unlikely(!createJString(env, sigName + 3, &javaSigName))) {
-    logger->printWarnMsg("Couldn't create java string.");
-    return false;
-  }
-
-  /* Create signal object */
-  insSignal = env->NewObject(classSignal, signal_init, javaSigName);
-  if (unlikely(insSignal == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't create signal object.");
-    env->DeleteLocalRef(javaSigName);
-    return false;
-  }
-
-  /* Setting signal handler. */
-  olderHandler = env->CallStaticObjectMethod(classSignal, signal_handle,
-                                             insSignal, handler);
-  /* If failure setting signal handler. */
-  if (unlikely(env->ExceptionOccurred() != NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't set signal handler.");
-    env->DeleteLocalRef(javaSigName);
-    env->DeleteLocalRef(insSignal);
-    return false;
-  }
-
-  /* Cleanup. */
-  env->DeleteLocalRef(olderHandler);
-  env->DeleteLocalRef(javaSigName);
-  env->DeleteLocalRef(insSignal);
-
-  return true;
-}
-
-/*!
- * \brief Convert string from C++ native to java.
- * \param env       [in] JNI environment object.
- * \param nativeStr [in] String in C++.
- * \param javaStr   [in,out] String object in java.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- */
-bool TSignalManager::createJString(JNIEnv *env, char *nativeStr,
-                                   jstring *javaStr) {
-  /* Sanity check. */
-  if (unlikely(nativeStr == NULL || strlen(nativeStr) == 0)) {
-    logger->printWarnMsg("Illegal native string.");
-    return false;
-  }
-
-  jbyteArray byteArray = NULL;
-  size_t strLen = strlen(nativeStr);
-
-  /* Creaet source byte array. */
-  byteArray = env->NewByteArray(strLen);
-  if (unlikely(byteArray == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't create byte array.");
-    return false;
-  }
-
-  /* Copy native string to byte array. */
-  env->SetByteArrayRegion(byteArray, 0, strLen, (jbyte *)nativeStr);
-  if (unlikely(env->ExceptionOccurred() != NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't copy to byte array.");
-    env->DeleteLocalRef(byteArray);
-    return false;
-  }
-
-  /* Create java string object. */
-  *javaStr = (jstring)env->NewObject(classString, string_init, byteArray);
-  /* if failure create java string. */
-  if (unlikely(*javaStr == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't create string object.");
-    env->DeleteLocalRef(byteArray);
-    return false;
-  }
-
-  /* Cleanup. */
-  env->DeleteLocalRef(byteArray);
-
-  return true;
-}
-
-/*!
- * \brief Getting default signal handler in JVM.
- * \param env [in] JNI environment object.
- * \return Process is succeed, if value is true.<br>
- *         Process is failure, if value is false.
- */
-bool TSignalManager::getDefaultSignalHandler(JNIEnv *env) {
-  /* Find "SignalHandler" class. */
-  jclass classSignalHandler = env->FindClass("Lsun/misc/SignalHandler;");
-  /* If failure signalhandler class. */
-  if (unlikely(classSignalHandler == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Failure getting class of default signal handler.");
-    return false;
-  }
-
-  /* Find static field. */
-  jfieldID sigDFL = env->GetStaticFieldID(classSignalHandler, "SIG_DFL",
-                                          "Lsun/misc/SignalHandler;");
-  /* If not found default signal handler. */
-  if (unlikely(sigDFL == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't get fieldID of default signal handler.");
-    env->DeleteLocalRef(classSignalHandler);
-    return false;
-  }
-
-  /* Get static field reference. */
-  jobject localSigDFL = env->GetStaticObjectField(classSignalHandler, sigDFL);
-  /* If failure getting field. */
-  if (unlikely(localSigDFL == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't get value of default signal handler.");
-    env->DeleteLocalRef(classSignalHandler);
-    return false;
-  }
-
-  /* Get global reference. */
-  signal_DFL = env->NewGlobalRef(localSigDFL);
-  if (unlikely(signal_DFL == NULL)) {
-    handlePendingException(env);
-
-    logger->printWarnMsg("Couldn't get global reference.");
-    env->DeleteLocalRef(localSigDFL);
-    env->DeleteLocalRef(classSignalHandler);
-    return false;
-  }
-
-  /* Cleanup. */
-  env->DeleteLocalRef(localSigDFL);
-  env->DeleteLocalRef(classSignalHandler);
-
-  return true;
-}
--- a/agent/src/heapstats-engines/signalManager.hpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/signalManager.hpp	Mon Apr 18 21:28:04 2016 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file signalManager.hpp
  * \brief This file is used by signal handling.
- * Copyright (C) 2011-2015 Nippon Telegraph and Telephone Corporation
+ * Copyright (C) 2011-2016 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
@@ -22,6 +22,9 @@
 #ifndef _SIGNAL_MNGR_H
 #define _SIGNAL_MNGR_H
 
+#include <jni.h>
+#include <signal.h>
+
 #include "util.hpp"
 
 /*!
@@ -31,146 +34,62 @@
  *                     But this value is always null.
  * \param data    [in] Data of received signal.<br>
  *                     But this value is always null.
- * \sa Please see JDK source about "siginfo" and "data" is always null.<br>
- *     jdk/src/share/native/sun/misc/NativeSignalHandler.c
  * \warning Function must be signal-safe.
  */
-typedef void (*TSignalHandler)(int signo, void *siginfo, void *data);
+typedef void (*TSignalHandler)(int signo, siginfo_t *siginfo, void *data);
+
+typedef struct structSignalHandlerChain {
+  TSignalHandler handler;
+  structSignalHandlerChain *next;
+} TSignalHandlerChain;
+
+typedef struct {
+  int sig;
+  const char *name;
+} TSignalMap;
+
 
 /*!
  * \brief This class is handling signal.
  */
 class TSignalManager {
- public:
-  /*!
-   * \brief TSignalManager constructor.
-   * \param env  [in] JNI environment object.
-   * \param proc [in] Pointer of signal callback.
-   */
-  TSignalManager(JNIEnv *env, TSignalHandler proc);
-
-  /*!
-   * \brief TSignalManager destructor.
-   */
-  virtual ~TSignalManager(void);
-
-  /*!
-   * \brief Add signal which is handled.
-   * \param env     [in] JNI environment object.
-   * \param sigName [in] Name of signal.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   */
-  bool catchSignal(JNIEnv *env, char *sigName);
 
-  /*!
-   * \brief Specify signal to ignore.
-   * \param env     [in] JNI environment object.
-   * \param sigName [in] Name of signal.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   */
-  bool ignoreSignal(JNIEnv *env, char *sigName);
-
-  /*!
-   * \brief Terminate handling signal.
-   * \param env [in] JNI environment object.
-   */
-  void terminate(JNIEnv *env);
+  private:
+    /*!
+     * \brief Signal number for this instance.
+     */
+    int signal;
 
-  /*!
-   * \brief Global initialization.
-   * \param env [in] JNI environment object.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   * \warning Please call only once from main thread.
-   */
-  static bool globalInitialize(JNIEnv *env);
-
-  /*!
-   * \brief Global finalize.
-   * \param env [in] JNI environment object.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   * \warning Please call only once from main thread.
-   */
-  static bool globalFinalize(JNIEnv *env);
+    /*!
+     * \brief SR_Handler in HotSpot VM
+     */
+    static TSignalHandler SR_Handler;
 
- protected:
-  /*!
-   * \brief Setting signal handle function.
-   * \param env     [in] JNI environment object.
-   * \param sigName [in] Name of signal.
-   * \param handler [in] Setting signal handler.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   */
-  virtual bool setSignalHandler(JNIEnv *env, char *sigName, jobject handler);
-
-  /*!
-   * \brief Convert string from C++ native to java.
-   * \param env       [in] JNI environment object.
-   * \param nativeStr [in] String in C++.
-   * \param javaStr   [in,out] String object in java.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   */
-  bool createJString(JNIEnv *env, char *nativeStr, jstring *javaStr);
-
-  /*!
-   * \brief Getting default signal handler in JVM.
-   * \param env [in] JNI environment object.
-   * \return Process is succeed, if value is true.<br>
-   *         Process is failure, if value is false.
-   */
-  static bool getDefaultSignalHandler(JNIEnv *env);
-
-  RELEASE_ONLY(private :)
+  public:
+    /*!
+     * \brief Find signal number from name.
+     * \param sig Signal name.
+     * \return Signal number. Return -1 if not found.
+     */
+    static int findSignal(const char *sig);
 
-  /*!
-   * \brief Object of "NativeSignalHandler" class information.
-   */
-  static jclass classNativeHandler;
-  /*!
-   * \brief Object of "Signal" class information.
-   */
-  static jclass classSignal;
-  /*!
-   * \brief Object of "String" class information.
-   */
-  static jclass classString;
+    /*!
+     * \brief TSignalManager constructor.
+     * \param sig Signal string.
+     */
+    TSignalManager(const char *sig);
 
-  /*!
-   * \brief Constructor of "NativeSignalHandler" class.
-   */
-  static jmethodID nativeHandler_init;
-  /*!
-   * \brief Constructor of "Signal" class.
-   */
-  static jmethodID signal_init;
-  /*!
-   * \brief Constructor of "String" class.
-   */
-  static jmethodID string_init;
-  /*!
-   * \brief Method "handle" of "Signal" class.
-   */
-  static jmethodID signal_handle;
+    /*!
+     * \brief TSignalManager destructor.
+     */
+    virtual ~TSignalManager(void);
 
-  /*!
-   * \brief Default signal handler.
-   */
-  static jobject signal_DFL;
-
-  /*!
-   * \brief Flag of load initialize data.
-   */
-  static bool loadFlag;
-
-  /*!
-   * \brief Orignal signal handler.
-   */
-  jobject insSignalHandler;
+    /*!
+     * \brief Add signal handler.
+     * \param handler [in] Function pointer for signal handler.
+     * \return true if new signal handler is added.
+     */
+    bool addHandler(TSignalHandler handler);
 };
 
 #endif  // _SIGNAL_MNGR_H
--- a/agent/src/heapstats-engines/vmFunctions.cpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/vmFunctions.cpp	Mon Apr 18 21:28:04 2016 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file vmFunctions.cpp
  * \brief This file includes functions in HotSpot VM.<br>
- * Copyright (C) 2014-2015 Yasumasa Suenaga
+ * Copyright (C) 2014-2016 Yasumasa Suenaga
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -147,6 +147,36 @@
     return false;
   }
 
+  /* Search "get_thread" function symbol. */
+  get_thread = (TGet_thread) this->symFinder->findSymbol(GET_THREAD_SYMBOL);
+  if (get_thread == NULL) { // for JDK 9
+    /* Search "ThreadLocalStorage::thread" function symbol. */
+    get_thread = (TGet_thread) this->symFinder->findSymbol(
+                                              THREADLOCALSTORAGE_THREAD_SYMBOL);
+    if (unlikely(get_thread == NULL)) {
+      logger->printWarnMsg("ThreadLocalStorage::thread() not found.");
+      return false;
+    }
+  }
+
+  /* Search "UserHandler" function symbol. */
+  userHandler = (TUserHandler) this->symFinder->findSymbol(USERHANDLER_SYMBOL);
+  if (unlikely(userHandler == NULL)) {
+    logger->printWarnMsg("UserHandler() not found.");
+    return false;
+  }
+
+  /* Search "SR_handler" function symbol. */
+  sr_handler = (TSR_Handler) this->symFinder->findSymbol(SR_HANDLER_SYMBOL);
+  if (sr_handler == NULL) { // for OpenJDK
+    sr_handler = (TSR_Handler) this->symFinder->findSymbol(
+                                                    SR_HANDLER_SYMBOL_FALLBACK);
+    if (sr_handler == NULL) {
+      logger->printWarnMsg("SR_handler() not found.");
+      return false;
+    }
+  }
+
   if (vmVal->getUseG1()) {
     inst->getG1VTableFromSymbol();
   }
--- a/agent/src/heapstats-engines/vmFunctions.hpp	Mon Apr 11 21:51:17 2016 +0900
+++ b/agent/src/heapstats-engines/vmFunctions.hpp	Mon Apr 18 21:28:04 2016 +0900
@@ -1,7 +1,7 @@
 /*!
  * \file vmFunctions.hpp
  * \brief This file includes functions in HotSpot VM.
- * Copyright (C) 2014-2015 Yasumasa Suenaga
+ * Copyright (C) 2014-2016 Yasumasa Suenaga
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -92,6 +92,28 @@
  */
 #define UNSAFE_PARK_SYMBOL "Unsafe_Park"
 
+/*!
+ * \brief Symbol of get_thread()
+ */
+#define GET_THREAD_SYMBOL "get_thread"
+
+/*!
+ * \brief Symbol of ThreadLocalStorage::thread()
+ */
+#define THREADLOCALSTORAGE_THREAD_SYMBOL "_ZN18ThreadLocalStorage6threadEv"
+
+/*!
+ * \brief Symbol of UserHandler()
+ */
+#define USERHANDLER_SYMBOL "_ZL11UserHandleriPvS_"
+
+/*!
+ * \brief Symbol of SR_handler()
+ */
+#define SR_HANDLER_SYMBOL          "_ZL10SR_handleriP7siginfoP8ucontext"
+#define SR_HANDLER_SYMBOL_FALLBACK "_ZL10SR_handleriP9siginfo_tP8ucontext"
+
+
 /* Function type definition */
 
 /*!
@@ -156,6 +178,43 @@
 typedef void (*TUnsafe_Park)(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
                              jlong time);
 
+/*!
+ * \brief JNI function of sun.misc.Unsafe#park() .
+ * \param env [in] JNI environment.
+ * \param unsafe [in] Unsafe object.
+ * \param isAbsolute [in] absolute.
+ * \param time [in] Park time.
+ */
+typedef void (*TUnsafe_Park)(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
+                             jlong time);
+
+/*!
+ * \brief Get C++ Thread instance.
+ * \return C++ Thread instance of this thread context.
+ */
+typedef void *(*TGet_thread)();
+
+/*!
+ * \brief User signal handler for HotSpot.
+ * \param sig Signal number.
+ * \param siginfo Signal information.
+ * \param context Thread context.
+ */
+typedef void (*TUserHandler)(int sig, void *siginfo, void *context);
+
+/*!
+ * \brief Thread suspend/resume signal handler in HotSpot.
+ * \param sig Signal number.
+ * \param siginfo Signal information.
+ * \param context Thread context.
+ */
+typedef void (*TSR_Handler)(int sig, siginfo_t *siginfo, ucontext_t *context);
+
+
+/* Exported function in libjvm.so */
+extern "C" void *JVM_RegisterSignal(jint sig, void *handler);
+
+
 /* extern variables */
 extern "C" void *VTableForTypeArrayOopClosure[2];
 extern "C" THeap_IsInPermanent is_in_permanent;
@@ -195,6 +254,21 @@
    */
   TUnsafe_Park unsafePark;
 
+  /*!
+   * \brief Function pointer for "get_thread()".
+   */
+  TGet_thread get_thread;
+
+  /*!
+   * \brief Function pointer for "UserHandler".
+   */
+  TUserHandler userHandler;
+
+  /*!
+   * \brief Function pointer for "SR_handler".
+   */
+  TSR_Handler sr_handler;
+
   /* Class of HeapStats for scanning variables in HotSpot VM */
   TSymbolFinder *symFinder;
 
@@ -260,6 +334,14 @@
   }
 
   inline void *GetUnsafe_ParkPointer(void) { return (void *)unsafePark; }
+
+  inline void *GetThread(void) {
+    return get_thread();
+  }
+
+  inline void *GetUserHandlerPointer(void) { return (void *)userHandler; }
+
+  inline void *GetSRHandlerPointer(void) { return (void *)sr_handler; }
 };
 
 #endif  // VMFUNCTIONS_H