changeset 13400:d2c2e33197d2

Dynamic loading of JMX or tool agent into modular application
author alanb
date Thu, 20 Apr 2017 16:56:33 +0100
parents f55aefad0862
children c150239dda02
files src/share/vm/classfile/modules.cpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/jvmtiExport.hpp src/share/vm/services/attachListener.cpp src/share/vm/services/diagnosticCommand.cpp
diffstat 6 files changed, 52 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/modules.cpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/classfile/modules.cpp	Thu Apr 20 16:56:33 2017 +0100
@@ -454,7 +454,6 @@
   // If the module is defined to the boot loader and an exploded build is being
   // used, prepend <java.home>/modules/modules_name, if it exists, to the system boot class path.
   if (loader == NULL &&
-      !Universe::is_module_initialized() &&
       !ClassLoader::has_jrt_entry()) {
     ClassLoader::add_to_exploded_build_list(module_symbol, CHECK);
   }
--- a/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Apr 20 16:56:33 2017 +0100
@@ -650,6 +650,8 @@
   template(addUses_signature,                          "(Ljava/lang/Module;Ljava/lang/Class;)V")                  \
   template(addProvides_name,                           "addProvides")                                             \
   template(addProvides_signature,                      "(Ljava/lang/Module;Ljava/lang/Class;Ljava/lang/Class;)V") \
+  template(loadModule_name,                            "loadModule")                                              \
+  template(loadModule_signature,                       "(Ljava/lang/String;)Ljava/lang/Module;")                  \
   template(transformedByAgent_name,                    "transformedByAgent")                                      \
   template(transformedByAgent_signature,               "(Ljava/lang/Module;)V")                                   \
   template(appendToClassPathForInstrumentation_name,   "appendToClassPathForInstrumentation")                     \
--- a/src/share/vm/prims/jvmtiExport.cpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/prims/jvmtiExport.cpp	Thu Apr 20 16:56:33 2017 +0100
@@ -54,7 +54,6 @@
 #include "runtime/os.inline.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
-#include "services/attachListener.hpp"
 #include "services/serviceUtil.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
@@ -2479,15 +2478,6 @@
   typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *);
 }
 
-jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
-  // get agent name and options
-  const char* agent = op->arg(0);
-  const char* absParam = op->arg(1);
-  const char* options = op->arg(2);
-
-  return load_agent_library(agent, absParam, options, st);
-}
-
 jint JvmtiExport::load_agent_library(const char *agent, const char *absParam,
                                      const char *options, outputStream* st) {
   char ebuf[1024];
--- a/src/share/vm/prims/jvmtiExport.hpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/prims/jvmtiExport.hpp	Thu Apr 20 16:56:33 2017 +0100
@@ -45,7 +45,6 @@
 class JvmtiManageCapabilities;
 class JvmtiEnv;
 class JvmtiThreadState;
-class AttachOperation;
 
 #define JVMTI_SUPPORT_FLAG(key)                                           \
   private:                                                                \
@@ -396,7 +395,6 @@
 #if INCLUDE_SERVICES
   // attach support
   static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
-  static jint load_agent_library(AttachOperation* op, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
 #endif
 
   // SetNativeMethodPrefix support
--- a/src/share/vm/services/attachListener.cpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/services/attachListener.cpp	Thu Apr 20 16:56:33 2017 +0100
@@ -100,6 +100,36 @@
   return JNI_OK;
 }
 
+// Implementation of "load" command.
+static jint load_agent(AttachOperation* op, outputStream* out) {
+  // get agent name and options
+  const char* agent = op->arg(0);
+  const char* absParam = op->arg(1);
+  const char* options = op->arg(2);
+
+  // If loading a java agent then need to ensure that the java.instrument module is loaded
+  if (strcmp(agent, "instrument") == 0) {
+    Thread* THREAD = Thread::current();
+    ResourceMark rm(THREAD);
+    HandleMark hm(THREAD);
+    JavaValue result(T_OBJECT);
+    Handle h_module_name = java_lang_String::create_from_str("java.instrument", THREAD);
+    JavaCalls::call_static(&result,
+                           SystemDictionary::module_Modules_klass(),
+                           vmSymbols::loadModule_name(),
+                           vmSymbols::loadModule_signature(),
+                           h_module_name,
+                           THREAD);
+    if (HAS_PENDING_EXCEPTION) {
+      java_lang_Throwable::print(PENDING_EXCEPTION, out);
+      CLEAR_PENDING_EXCEPTION;
+      return JNI_ERR;
+    }
+  }
+
+  return JvmtiExport::load_agent_library(agent, absParam, options, out);
+}
+
 // Implementation of "properties" command.
 // See also: PrintSystemPropertiesDCmd class
 static jint get_system_properties(AttachOperation* op, outputStream* out) {
@@ -282,7 +312,7 @@
   { "agentProperties",  get_agent_properties },
   { "datadump",         data_dump },
   { "dumpheap",         dump_heap },
-  { "load",             JvmtiExport::load_agent_library },
+  { "load",             load_agent },
   { "properties",       get_system_properties },
   { "threaddump",       thread_dump },
   { "inspectheap",      heap_inspection },
--- a/src/share/vm/services/diagnosticCommand.cpp	Thu Apr 13 17:36:28 2017 +0100
+++ b/src/share/vm/services/diagnosticCommand.cpp	Thu Apr 20 16:56:33 2017 +0100
@@ -42,6 +42,21 @@
 #include "utilities/macros.hpp"
 #include "oops/objArrayOop.inline.hpp"
 
+
+static void loadAgentModule(TRAPS) {
+  ResourceMark rm(THREAD);
+  HandleMark hm(THREAD);
+
+  JavaValue result(T_OBJECT);
+  Handle h_module_name = java_lang_String::create_from_str("jdk.management.agent", CHECK);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::loadModule_name(),
+                         vmSymbols::loadModule_signature(),
+                         h_module_name,
+                         THREAD);
+}
+
 void DCmdRegistrant::register_dcmds(){
   // Registration of the diagnostic commands
   // First argument specifies which interfaces will export the command
@@ -753,6 +768,7 @@
     // the remote management server.
     // throw java.lang.NoSuchMethodError if the method doesn't exist
 
+    loadAgentModule(CHECK);
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
     instanceKlassHandle ik (THREAD, k);
@@ -826,6 +842,7 @@
     // the local management server
     // throw java.lang.NoSuchMethodError if method doesn't exist
 
+    loadAgentModule(CHECK);
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
     instanceKlassHandle ik (THREAD, k);
@@ -843,6 +860,7 @@
     // management server
     // throw java.lang.NoSuchMethodError if method doesn't exist
 
+    loadAgentModule(CHECK);
     Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
     Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
     instanceKlassHandle ik (THREAD, k);
@@ -864,6 +882,7 @@
   // invoke getManagementAgentStatus() method to generate the status info
   // throw java.lang.NoSuchMethodError if method doesn't exist
 
+  loadAgentModule(CHECK);
   Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
   Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
   instanceKlassHandle ik (THREAD, k);