From 40459bd1e57eba466da1c0ace9f2ce0c407f9fc1 Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Sun, 6 Sep 2009 23:58:54 +0200 Subject: [PATCH] * src/native/native.hpp (NativeAgent, NativeAgents): Added new classes for 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 | 113 ++++++++++++++++++++++++++++++++--- src/native/native.hpp | 36 +++++++++++- src/vm/vm.cpp | 133 +++++++++++++----------------------------- src/vm/vm.hpp | 3 + 4 files changed, 182 insertions(+), 103 deletions(-) diff --git a/src/native/native.cpp b/src/native/native.cpp index 3c5e7b4c6..bc47238e8 100644 --- a/src/native/native.cpp +++ b/src/native/native.cpp @@ -57,10 +57,6 @@ #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::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. diff --git a/src/native/native.hpp b/src/native/native.hpp index c373e96f1..4a0b4c3c3 100644 --- a/src/native/native.hpp +++ b/src/native/native.hpp @@ -32,6 +32,7 @@ #ifdef __cplusplus #include #include +#include #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 _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 ********************************************************/ diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index f83e80e74..7aff240f0 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -100,10 +100,6 @@ #include "vm/jit/trap.hpp" -#if defined(ENABLE_JVMTI) -# include "native/jvmti/cacaodbg.h" -#endif - #if defined(ENABLE_VMLOG) #include #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:= library to load containg JVMTI agent"); - puts (" for jdwp help use: -agentlib:jdwp=help"); - puts(" -agentpath:= path to library containg JVMTI agent"); +#if defined(ENABLE_JVMTI) + puts(" -agentlib:="); + puts(" load native agent library by library name"); + puts(" for additional help use: -agentlib:jdwp=help"); + puts(" -agentpath:="); + 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=,server=(y|n),suspend(y|n) */ - puts(" -Xdebug enable remote debugging\n"); - puts(" -Xrunjdwp transport=[dt_socket|...],address=,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++; diff --git a/src/vm/vm.hpp b/src/vm/vm.hpp index 30242d4f0..e57c1b958 100644 --- a/src/vm/vm.hpp +++ b/src/vm/vm.hpp @@ -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: -- 2.25.1