* src/native/native.hpp (NativeAgent, NativeAgents): Added new classes for
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Sun, 6 Sep 2009 21:58:54 +0000 (23:58 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Sun, 6 Sep 2009 21:58:54 +0000 (23:58 +0200)
handling JVMTI agent loading.
* src/native/native.cpp: Implemented methods for above classes.
* src/vm/vm.hpp (VM): Added table to hold all registered agents.
* src/vm/vm.cpp (VM::VM): Agents are now correctly registered and loaded
during VM startup.

src/native/native.cpp
src/native/native.hpp
src/vm/vm.cpp
src/vm/vm.hpp

index 3c5e7b4c68641e94c972b261bddedd5d55decd3c..bc47238e881de7587ce3fe5a815a7cfa93748e92 100644 (file)
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.hpp"
 
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
 
 /* native_make_overloaded_function *********************************************
 
@@ -448,11 +444,6 @@ void* NativeMethods::resolve_method(methodinfo* m)
                        printf("JNI ]\n");
 #endif
 
-#if defined(ENABLE_JVMTI)
-       /* fire Native Method Bind event */
-       if (jvmti) jvmti_NativeMethodBind(m, f, &f);
-#endif
-
        // Symbol not found?  Throw an exception.
        if (symbol == NULL) {
                if (opt_verbosejni)
@@ -728,6 +719,110 @@ void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloade
 }
 
 
+/**
+ * Registers a new native agent by specified by it's library name
+ * and with an optional options string.
+ *
+ * @param library Name of the native agent library.
+ * @param options The options string or NULL if not specified.
+ */
+#if defined(ENABLE_JVMTI)
+void NativeAgents::register_agent_library(char* library, char* options)
+{
+       NativeAgent na(library, options);
+
+       // Insert native agent into list of agents.
+       _agents.push_back(na);
+}
+#endif
+
+
+/**
+ * Registers a new native agent by specified by a path to it's library
+ * and with an optional options string.
+ *
+ * @param path Path of the native agent library.
+ * @param options The options string or NULL if not specified.
+ */
+#if defined(ENABLE_JVMTI)
+void NativeAgents::register_agent_path(char* path, char* options)
+{
+       os::abort("NativeAgents::register_agent_library: Implement me!");
+}
+#endif
+
+
+/**
+ * Loads all registered native agents and in turn calls their exported
+ * start-up functions (Agent_OnLoad). If one of the agents reports an
+ * error during start-up, the loading is stopped.
+ *
+ * @return True if all agents were loaded successfully, false if
+ * one of them was not found or reported an error.
+ */
+#if defined(ENABLE_JVMTI)
+bool NativeAgents::load_agents()
+{
+       // Iterate over all registered agents.
+       for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
+               NativeAgent& na = *(it);
+
+               // Construct agent library name.
+               size_t len =
+                       os::strlen(NATIVE_LIBRARY_PREFIX) +
+                       os::strlen(na.get_library()) +
+                       os::strlen(NATIVE_LIBRARY_SUFFIX) +
+                       os::strlen("0");
+
+               char* p = MNEW(char, len);
+
+               os::strcpy(p, NATIVE_LIBRARY_PREFIX);
+               os::strcat(p, na.get_library());
+               os::strcat(p, NATIVE_LIBRARY_SUFFIX);
+
+               utf* u = utf_new_char(p);
+
+               MFREE(p, char, len);
+
+               // Construct new native library.
+               NativeLibrary nl(u);
+
+               // Try to open the library.
+               if (nl.open() == NULL)
+                       return false;
+
+               // Resolve Agent_OnLoad function.
+               void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
+
+               // Call Agent_OnLoad function if present.
+               if (onload != NULL) {
+                       JNIEXPORT jint (JNICALL *Agent_OnLoad) (JavaVM*, char*, void*);
+                       JavaVM* vm = VM::get_current()->get_javavm();
+
+                       Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
+
+                       jint result = Agent_OnLoad(vm, na.get_options(), NULL);
+
+                       // Check for error in Agent_OnLoad.
+                       if (result != 0) {
+                               nl.close();
+                               return false;
+                       }
+               }
+
+               // According to the interface spec, the library _must_ export
+               // a start-up function.
+               else {
+                       log_println("NativeAgents::load_agents: Native agent library does not export Agent_OnLoad");
+                       return false;
+               }
+       }
+
+       return true;
+}
+#endif
+
+
 /* native_new_and_init *********************************************************
 
    Creates a new object on the heap and calls the initializer.
index c373e96f146f17071e694f86f6d79c4df262dc07..4a0b4c3c3795ec671af05b5fa24d06020fcb2d22 100644 (file)
@@ -32,6 +32,7 @@
 #ifdef __cplusplus
 #include <map>
 #include <set>
+#include <vector>
 #endif
 
 #include "native/jni.hpp"
@@ -110,7 +111,7 @@ public:
        bool  is_loaded(NativeLibrary& library);
        void* resolve_symbol(utf* symbolname, classloader_t* classloader);
 };
-#endif
+#endif /* defined(ENABLE_DL) */
 
 
 /**
@@ -157,6 +158,39 @@ public:
        void* find_registered_method(methodinfo* m);
 };
 
+
+#if defined(ENABLE_JVMTI)
+/**
+ * Represents a registered native agent.
+ */
+class NativeAgent {
+private:
+       char* _library;
+       char* _options;
+
+public:
+       NativeAgent(char* library, char* options) : _library(library), _options(options) {}
+
+       char* get_library() const { return _library; }
+       char* get_options() const { return _options; }
+};
+
+
+/**
+ * Table containing all native agent libraries.
+ */
+class NativeAgents {
+private:
+       std::vector<NativeAgent> _agents;
+
+public:
+       void register_agent_library(char* library, char* options);
+       void register_agent_path(char* path, char* options);
+       bool load_agents();
+       bool unload_agents();
+};
+#endif /* defined(ENABLE_JVMTI) */
+
 #endif
 
 /* function prototypes ********************************************************/
index f83e80e7429d7711e3aefe724c7f6f0cf0347c45..7aff240f09e7f86f220e1acd67f94741a119a4f5 100644 (file)
 
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
 #if defined(ENABLE_VMLOG)
 #include <vmlog_cacao.h>
 #endif
@@ -238,12 +234,10 @@ enum {
 
        OPT_SS,
 
-#ifdef ENABLE_JVMTI
-       OPT_DEBUG,
-       OPT_XRUNJDWP,
-       OPT_NOAGENT,
+#if defined(ENABLE_JVMTI)
        OPT_AGENTLIB,
        OPT_AGENTPATH,
+       OPT_RUN,
 #endif
 
 #if defined(ENABLE_DEBUG_FILTER)
@@ -340,7 +334,7 @@ opt_struct opts[] = {
 #endif
 
        /* JVMTI Agent Command Line Options */
-#ifdef ENABLE_JVMTI
+#if defined(ENABLE_JVMTI)
        { "agentlib:",         true,  OPT_AGENTLIB },
        { "agentpath:",        true,  OPT_AGENTPATH },
 #endif
@@ -354,11 +348,11 @@ opt_struct opts[] = {
        { "Xbootclasspath/p:", true,  OPT_BOOTCLASSPATH_P },
        { "Xbootclasspath/c:", true,  OPT_BOOTCLASSPATH_C },
 
-#ifdef ENABLE_JVMTI
-       { "Xdebug",            false, OPT_DEBUG },
-       { "Xnoagent",          false, OPT_NOAGENT },
-       { "Xrunjdwp",          true,  OPT_XRUNJDWP },
-#endif 
+#if defined(ENABLE_JVMTI)
+       { "Xdebug",            false, OPT_IGNORE },
+       { "Xnoagent",          false, OPT_IGNORE },
+       { "Xrun",              true,  OPT_RUN },
+#endif
 
        { "Xms",               true,  OPT_MS },
        { "ms",                true,  OPT_MS },
@@ -431,16 +425,18 @@ void usage(void)
        puts("    -dsa | -disablesystemassertions");
        puts("                             disable system assertions");
 
-#ifdef ENABLE_JVMTI
-       puts("    -agentlib:<agent-lib-name>=<options>  library to load containg JVMTI agent");
-       puts ("                                         for jdwp help use: -agentlib:jdwp=help");
-       puts("    -agentpath:<path-to-agent>=<options>  path to library containg JVMTI agent");
+#if defined(ENABLE_JVMTI)
+       puts("    -agentlib:<agent-lib-name>=<options>");
+       puts("                             load native agent library by library name");
+       puts("                             for additional help use: -agentlib:jdwp=help");
+       puts("    -agentpath:<path-to-agent>=<options>");
+       puts("                             load native agent library by full pathname");
 #endif
 
        /* exit with error code */
 
        exit(1);
-}   
+}
 
 
 static void Xusage(void)
@@ -468,14 +464,6 @@ static void Xusage(void)
        puts("    -Xprof[:bb]              collect and print profiling data");
 #endif
 
-#if defined(ENABLE_JVMTI)
-    /* -Xdebug option depend on gnu classpath JDWP options. options: 
-        transport=dt_socket,address=<hostname:port>,server=(y|n),suspend(y|n) */
-       puts("    -Xdebug                  enable remote debugging\n");
-       puts("    -Xrunjdwp transport=[dt_socket|...],address=<hostname:port>,server=[y|n],suspend=[y|n]\n");
-       puts("                             enable remote debugging\n");
-#endif 
-
        /* exit with error code */
 
        exit(1);
@@ -682,13 +670,6 @@ VM::VM(JavaVMInitArgs* vm_args)
        bool  opt_version;
        bool  opt_exit;
 
-#if defined(ENABLE_JVMTI)
-       lt_dlhandle  handle;
-       char *libname, *agentarg;
-       bool jdwp,agentbypath;
-       jdwp = agentbypath = false;
-#endif
-
 #if defined(ENABLE_JNI)
        /* Check the JNI version requested. */
 
@@ -744,11 +725,6 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        _starttime = builtin_currenttimemillis();
 
-#if defined(ENABLE_JVMTI)
-       /* initialize JVMTI related  **********************************************/
-       jvmti = false;
-#endif
-
        /* iterate over all passed options */
 
        while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
@@ -897,42 +873,34 @@ VM::VM(JavaVMInitArgs* vm_args)
                        break;
 
 #if defined(ENABLE_JVMTI)
-               case OPT_DEBUG:
-                       /* this option exists only for compatibility reasons */
-                       break;
+               case OPT_AGENTLIB:
+                       // Parse option argument.
+                       p = strchr(opt_arg, '=');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-               case OPT_NOAGENT:
-                       /* I don't know yet what Xnoagent should do. This is only for 
-                          compatiblity with eclipse - motse */
+                       _nativeagents.register_agent_library(opt_arg, p);
                        break;
 
-               case OPT_XRUNJDWP:
-                       agentbypath = true;
-                       jvmti       = true;
-                       jdwp        = true;
-
-                       len =
-                               strlen(CACAO_LIBDIR) +
-                               strlen("/libjdwp.so=") +
-                               strlen(opt_arg) +
-                               strlen("0");
-
-                       agentarg = MNEW(char, len);
+               case OPT_AGENTPATH:
+                       // Parse option argument.
+                       p = strchr(opt_arg, '=');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-                       strcpy(agentarg, CACAO_LIBDIR);
-                       strcat(agentarg, "/libjdwp.so=");
-                       strcat(agentarg, &opt_arg[1]);
+                       _nativeagents.register_agent_path(opt_arg, p);
                        break;
 
-               case OPT_AGENTPATH:
-                       agentbypath = true;
+               case OPT_RUN:
+                       // Parse option argument.
+                       p = strchr(opt_arg, ':');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-               case OPT_AGENTLIB:
-                       jvmti = true;
-                       agentarg = opt_arg;
+                       _nativeagents.register_agent_library(opt_arg, p);
                        break;
 #endif
-                       
+
                case OPT_MX:
                case OPT_MS:
                case OPT_SS:
@@ -1281,18 +1249,6 @@ VM::VM(JavaVMInitArgs* vm_args)
        if (opt_PrintConfig)
                print_run_time_config();
 
-#if defined(ENABLE_JVMTI)
-       if (jvmti) {
-               jvmti_set_phase(JVMTI_PHASE_ONLOAD);
-               jvmti_agentload(agentarg, agentbypath, &handle, &libname);
-
-               if (jdwp)
-                       MFREE(agentarg, char, strlen(agentarg));
-
-               jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
-       }
-#endif
-
        /* initialize the garbage collector */
 
        gc_init(opt_heapmaxsize, opt_heapstartsize);
@@ -1327,6 +1283,12 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        utf8_init();
 
+#if defined(ENABLE_JVMTI)
+       // AFTER: utf8_init
+       if (!_nativeagents.load_agents())
+               os::abort("vm_create: load_agents failed");
+#endif
+
        /* AFTER: thread_preinit */
 
        _suckclasspath.add_from_property("java.endorsed.dirs");
@@ -1475,17 +1437,6 @@ VM::VM(JavaVMInitArgs* vm_args)
 # endif
 #endif
 
-#if defined(ENABLE_JVMTI)
-# if defined(ENABLE_GC_CACAO)
-       /* XXX this will not work with the new indirection cells for classloaders!!! */
-       assert(0);
-# endif
-       if (jvmti) {
-               /* add agent library to native library hashtable */
-               native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
-       }
-#endif
-
        /* Increment the number of VMs. */
 
        vms++;
@@ -1716,10 +1667,6 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
        typeinfo_test();
 #endif
 
-#if defined(ENABLE_JVMTI)
-       jvmti_set_phase(JVMTI_PHASE_LIVE);
-#endif
-
        /* set ThreadMXBean variables */
 
 //     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
index 30242d4f07e6b604d212c121d4f6059b27269307..e57c1b958054cb535c55b124c168451ddc70f5ef 100644 (file)
@@ -77,6 +77,9 @@ private:
 #endif
        NativeLibraries _nativelibraries; ///< Native library table.
        NativeMethods   _nativemethods;   ///< Native methods table.
+#if defined(ENABLE_JVMTI)
+       NativeAgents    _nativeagents;    ///< Native agents table.
+#endif
        SuckClasspath   _suckclasspath;   ///< Classpath entries list.
 
 public: