/* src/native/native.cpp - native library support
- Copyright (C) 1996-2005, 2006, 2007, 2008
+ Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
-#include "vm/types.h"
+#include <algorithm>
+#include <functional>
+#include <map>
-#include "mm/memory.h"
+#include "mm/memory.hpp"
#include "native/jni.hpp"
#include "native/native.hpp"
#include "threads/mutex.hpp"
-#include "toolbox/avl.h"
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
+#include "vm/hook.hpp"
#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/os.hpp"
-#include "vm/resolve.h"
+#include "vm/resolve.hpp"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.hpp"
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-
-/* global variables ***********************************************************/
-
-static avl_tree_t *tree_native_methods;
-
-#if defined(ENABLE_DL)
-static hashtable *hashtable_library;
-#endif
-
-
-/* prototypes *****************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
-
-
-/* native_init *****************************************************************
-
- Initializes the native subsystem.
-
-*******************************************************************************/
-
-bool native_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("native_init");
-
-#if defined(ENABLE_DL)
- /* initialize library hashtable, 10 entries should be enough */
-
- hashtable_library = NEW(hashtable);
-
- hashtable_create(hashtable_library, 10);
-#endif
-
- /* initialize the native methods table */
-
- tree_native_methods = avl_create(&native_tree_native_methods_comparator);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* native_tree_native_methods_comparator ***************************************
-
- Comparison function for AVL tree of native methods.
-
- IN:
- treenode....node in the tree
- node........node to compare with tree-node
-
- RETURN VALUE:
- -1, 0, +1
-
-*******************************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
-{
- const native_methods_node_t *treenmn;
- const native_methods_node_t *nmn;
-
- treenmn = (native_methods_node_t*) treenode;
- nmn = (native_methods_node_t*) node;
-
- /* these are for walking the tree */
-
- if (treenmn->classname < nmn->classname)
- return -1;
- else if (treenmn->classname > nmn->classname)
- return 1;
-
- if (treenmn->name < nmn->name)
- return -1;
- else if (treenmn->name > nmn->name)
- return 1;
-
- if (treenmn->descriptor < nmn->descriptor)
- return -1;
- else if (treenmn->descriptor > nmn->descriptor)
- return 1;
-
- /* all pointers are equal, we have found the entry */
-
- return 0;
-}
-
/* native_make_overloaded_function *********************************************
}
-/* native_method_register ******************************************************
-
- Register a native method in the native method table.
-
-*******************************************************************************/
-
-void native_method_register(utf *classname, const JNINativeMethod *methods,
- int32_t count)
+bool operator< (const NativeMethod& first, const NativeMethod& second)
{
- native_methods_node_t *nmn;
- utf *name;
- utf *descriptor;
- int32_t i;
+ if (first._classname < second._classname)
+ return true;
+ else if (first._classname > second._classname)
+ return false;
+
+ if (first._name < second._name)
+ return true;
+ else if (first._name > second._name)
+ return false;
+
+ if (first._descriptor < second._descriptor)
+ return true;
+ else if (first._descriptor > second._descriptor)
+ return false;
+
+ // All pointers are equal, we have found the entry.
+ return false;
+}
- /* insert all methods passed */
- for (i = 0; i < count; i++) {
+/**
+ * Register native methods with the VM. This is done by inserting
+ * them into the native method table.
+ *
+ * @param classname
+ * @param methods Native methods array.
+ * @param count Number of methods in the array.
+ */
+void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
+{
+ // Insert all methods passed */
+ for (size_t i = 0; i < count; i++) {
if (opt_verbosejni) {
printf("[Registering JNI native method ");
utf_display_printable_ascii_classname(classname);
printf(".%s]\n", methods[i].name);
}
- /* generate the utf8 names */
-
- name = utf_new_char(methods[i].name);
- descriptor = utf_new_char(methods[i].signature);
-
- /* allocate a new tree node */
+ // Generate the UTF8 names.
+ utf* name = utf_new_char(methods[i].name);
+ utf* signature = utf_new_char(methods[i].signature);
- nmn = NEW(native_methods_node_t);
+ NativeMethod nm(classname, name, signature, methods[i].fnPtr);
- nmn->classname = classname;
- nmn->name = name;
- nmn->descriptor = descriptor;
- nmn->function = (functionptr) (ptrint) methods[i].fnPtr;
-
- /* insert the method into the tree */
-
- avl_insert(tree_native_methods, nmn);
+ // Insert the method into the table.
+ _methods.insert(nm);
}
}
-/* native_method_find **********************************************************
-
- Find a native method in the native method table.
-
-*******************************************************************************/
-
-static functionptr native_method_find(methodinfo *m)
-{
- native_methods_node_t tmpnmn;
- native_methods_node_t *nmn;
-
- /* fill the temporary structure used for searching the tree */
-
- tmpnmn.classname = m->clazz->name;
- tmpnmn.name = m->name;
- tmpnmn.descriptor = m->descriptor;
-
- /* find the entry in the AVL-tree */
-
- nmn = (native_methods_node_t*) avl_find(tree_native_methods, &tmpnmn);
-
- if (nmn == NULL)
- return NULL;
-
- return nmn->function;
-}
-
-
-/* native_method_resolve *******************************************************
-
- Resolves a native method, maybe from a dynamic library.
-
- IN:
- m ... methodinfo of the native Java method to resolve
-
- RESULT:
- pointer to the resolved method (symbol)
-
-*******************************************************************************/
-
-functionptr native_method_resolve(methodinfo *m)
+/**
+ * Resolves a native method, maybe from a dynamic library.
+ *
+ * @param m Method structure of the native Java method to resolve.
+ *
+ * @return Pointer to the resolved method (symbol).
+ */
+void* NativeMethods::resolve_method(methodinfo* m)
{
- utf *name;
- utf *newname;
- functionptr f;
-#if defined(ENABLE_DL)
- classloader_t *cl;
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne;
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- methodinfo *method_findNative;
- java_handle_t *s;
-#endif
-
- /* verbose output */
-
+ // Verbose output.
if (opt_verbosejni) {
printf("[Dynamic-linking native method ");
utf_display_printable_ascii_classname(m->clazz->name);
/* generate method symbol string */
- name = native_method_symbol(m->clazz->name, m->name);
+ utf* name = native_method_symbol(m->clazz->name, m->name);
/* generate overloaded function (having the types in it's name) */
- newname = native_make_overloaded_function(name, m->descriptor);
-
- /* check the library hash entries of the classloader of the
- methods's class */
-
- f = NULL;
-
-#if defined(ENABLE_DL)
- /* Get the classloader. */
-
- cl = class_get_classloader(m->clazz);
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
+ utf* newname = native_make_overloaded_function(name, m->descriptor);
- key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */
- slot = key & (hashtable_library->size - 1);
- le = (hashtable_library_loader_entry*) hashtable_library->ptr[slot];
+ // Try to find the symbol.
+ void* symbol;
- /* iterate through loaders in this hash slot */
+ // Try to find the native method symbol in the native methods registered
+ // with the VM.
+ symbol = find_registered_method(m);
- while ((le != NULL) && (f == NULL)) {
- /* iterate through names in this loader */
+ if (symbol != NULL)
+ if (opt_verbosejni)
+ printf("internal ]\n");
- ne = le->namelink;
-
- while ((ne != NULL) && (f == NULL)) {
- f = (functionptr) (ptrint) os::dlsym(ne->handle, name->text);
+#if defined(ENABLE_DL)
+ classloader_t* classloader;
+ if (symbol == NULL) {
+ // Get the classloader.
+ classloader = class_get_classloader(m->clazz);
- if (f == NULL)
- f = (functionptr) (ptrint) os::dlsym(ne->handle, newname->text);
+ // Resolve the native method name from the native libraries.
+ NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
- ne = ne->hashlink;
- }
+ symbol = libraries.resolve_symbol(name, classloader);
- le = le->hashlink;
+ if (symbol == NULL)
+ symbol = libraries.resolve_symbol(newname, classloader);
}
# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- if (f == NULL) {
+ if (symbol == NULL) {
/* We can resolve the function directly from
java.lang.ClassLoader as it's a static function. */
/* XXX should be done in native_init */
- method_findNative =
+ methodinfo* method_findNative =
class_resolveclassmethod(class_java_lang_ClassLoader,
utf_findNative,
utf_java_lang_ClassLoader_java_lang_String__J,
class_java_lang_ClassLoader,
true);
- if (method_findNative == NULL)
- return NULL;
-
- /* try the normal name */
-
- s = javastring_new(name);
-
- f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
- NULL, cl, s);
+ if (method_findNative != NULL) {
+ // Try the normal name.
+ java_handle_t* s = javastring_new(name);
+ symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
- /* if not found, try the mangled name */
-
- if (f == NULL) {
- s = javastring_new(newname);
-
- f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
- NULL, cl, s);
+ // If not found, try the mangled name.
+ if (symbol == NULL) {
+ s = javastring_new(newname);
+ symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+ }
}
}
# endif
- if (f != NULL)
+ if (symbol != NULL)
if (opt_verbosejni)
printf("JNI ]\n");
#endif
- /* If not found, try to find the native function symbol in the
- main program. */
-
- if (f == NULL) {
- f = native_method_find(m);
-
- if (f != NULL)
- if (opt_verbosejni)
- printf("internal ]\n");
- }
-
-#if defined(ENABLE_JVMTI)
- /* fire Native Method Bind event */
- if (jvmti) jvmti_NativeMethodBind(m, f, &f);
-#endif
-
- /* no symbol found? throw exception */
-
- if (f == NULL) {
+ // Symbol not found? Throw an exception.
+ if (symbol == NULL) {
if (opt_verbosejni)
printf("failed ]\n");
exceptions_throw_unsatisfiedlinkerror(m->name);
}
- return f;
-}
+ // Hook point just after method resolving finished.
+ Hook::native_resolved(m, symbol, &symbol);
+ return symbol;
+}
-/* native_library_open *********************************************************
- Open a native library with the given utf8 name.
+/**
+ * Try to find the given method in the native methods registered with
+ * the VM.
+ *
+ * @param m Method structure.
+ *
+ * @return Pointer to function if found, NULL otherwise.
+ */
+void* NativeMethods::find_registered_method(methodinfo* m)
+{
+ NativeMethod nm(m);
+ std::set<NativeMethod>::iterator it = _methods.find(nm);
- IN:
- filename ... filename of the library to open
+ if (it == _methods.end())
+ return NULL;
- RETURN:
- handle of the opened library
+ return (*it).get_function();
+}
-*******************************************************************************/
+/**
+ * Open this native library.
+ *
+ * @return File handle on success, NULL otherwise.
+ */
#if defined(ENABLE_DL)
-void* native_library_open(utf *filename)
+void* NativeLibrary::open()
{
- void* handle;
-
if (opt_verbosejni) {
printf("[Loading native library ");
- utf_display_printable_ascii(filename);
+ utf_display_printable_ascii(_filename);
printf(" ... ");
}
- /* try to open the library */
+ // Sanity check.
+ assert(_filename != NULL);
- handle = os::dlopen(filename->text, RTLD_LAZY);
+ // Try to open the library.
+ _handle = os::dlopen(_filename->text, RTLD_LAZY);
- if (handle == NULL) {
+ if (_handle == NULL) {
if (opt_verbosejni)
printf("failed ]\n");
- if (opt_verbose) {
- log_start();
- log_print("native_library_open: os::dlopen failed: ");
- log_print(dlerror());
- log_finish();
- }
+ if (opt_PrintWarnings)
+ log_println("NativeLibrary::open: os::dlopen failed: %s", os::dlerror());
return NULL;
}
if (opt_verbosejni)
printf("OK ]\n");
- return handle;
+ return _handle;
}
#endif
-/* native_library_close ********************************************************
-
- Close the native library of the given handle.
-
- IN:
- handle ... handle of the open library
-
-*******************************************************************************/
-
+/**
+ * Close this native library.
+ */
#if defined(ENABLE_DL)
-void native_library_close(void* handle)
+void NativeLibrary::close()
{
- int result;
-
if (opt_verbosejni) {
printf("[Unloading native library ");
/* utf_display_printable_ascii(filename); */
printf(" ... ");
}
- /* Close the library. */
+ // Sanity check.
+ assert(_handle != NULL);
- result = os::dlclose(handle);
+ // Close the library.
+ int result = os::dlclose(_handle);
if (result != 0) {
- if (opt_verbose) {
- log_start();
- log_print("native_library_close: os::dlclose failed: ");
- log_print(dlerror());
- log_finish();
- }
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
+ if (opt_PrintWarnings)
+ log_println("NativeLibrary::close: os::dlclose failed: %s", os::dlerror());
}
+
+ if (opt_verbosejni)
+ printf("OK ]\n");
}
#endif
-/* native_library_add **********************************************************
-
- Adds an entry to the native library hashtable.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void native_library_add(utf *filename, classloader_t *loader, void* handle)
+/**
+ * Load this native library and initialize it, if possible.
+ *
+ * @param env JNI environment.
+ *
+ * @return true if library loaded successfully, false otherwise.
+ */
+bool NativeLibrary::load(JNIEnv* env)
{
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne; /* library name */
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
-
- hashtable_library->mutex->lock();
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_library->size - 1);
- le = (hashtable_library_loader_entry*) hashtable_library->ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (le) {
- if (le->loader == loader)
- break;
-
- le = le->hashlink; /* next element in external chain */
+#if defined(ENABLE_DL)
+ if (_filename == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
}
- /* no loader found? create a new entry */
-
- if (le == NULL) {
- le = NEW(hashtable_library_loader_entry);
+ // Is the library already loaded?
+ if (is_loaded())
+ return true;
- le->loader = loader;
- le->namelink = NULL;
+ // Open the library.
+ open();
- /* insert entry into hashtable */
+ if (_handle == NULL)
+ return false;
- le->hashlink =
- (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
- hashtable_library->ptr[slot] = le;
-
- /* update number of hashtable-entries */
+# if defined(ENABLE_JNI)
+ // Resolve JNI_OnLoad function.
+ void* onload = os::dlsym(_handle, "JNI_OnLoad");
- hashtable_library->entries++;
- }
+ if (onload != NULL) {
+ JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
+ JavaVM *vm;
+ JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
- /* search for library name */
+ env->GetJavaVM(&vm);
- ne = le->namelink;
+ jint version = JNI_OnLoad(vm, NULL);
- while (ne) {
- if (ne->name == filename) {
- hashtable_library->mutex->unlock();
- return;
+ // If the version is not 1.2 and not 1.4 the library cannot be
+ // loaded.
+ if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+ os::dlclose(_handle);
+ return false;
}
-
- ne = ne->hashlink; /* next element in external chain */
}
+# endif
- /* not found? add the library name to the classloader */
-
- ne = NEW(hashtable_library_name_entry);
+ // Insert the library name into the native library table.
+ NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
+ nativelibraries.add(*this);
- ne->name = filename;
- ne->handle = handle;
+ return true;
+#else
+ os::abort("NativeLibrary::load: Not available in this configuration.");
- /* insert entry into external chain */
+ // Keep the compiler happy.
+ return false;
+#endif
+}
- ne->hashlink = le->namelink;
- le->namelink = ne;
- hashtable_library->mutex->unlock();
+/**
+ * Checks if this native library is loaded.
+ *
+ * @return true if loaded, false otherwise.
+ */
+#if defined(ENABLE_DL)
+bool NativeLibrary::is_loaded()
+{
+ NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
+ return libraries.is_loaded(*this);
}
#endif
-/* native_library_find *********************************************************
-
- Find an entry in the native library hashtable.
+/**
+ * Resolve the given symbol in this native library.
+ *
+ * @param symbolname Symbol name.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibrary::resolve_symbol(utf* symbolname) const
+{
+ return os::dlsym(_handle, symbolname->text);
+}
-*******************************************************************************/
+/**
+ * Add the given native library to the native libraries table.
+ *
+ * @param library Native library to insert.
+ */
#if defined(ENABLE_DL)
-hashtable_library_name_entry *native_library_find(utf *filename,
- classloader_t *loader)
+void NativeLibraries::add(NativeLibrary& library)
{
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne; /* library name */
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
+ // Make the container thread-safe.
+ _mutex.lock();
- /* normally addresses are aligned to 4, 8 or 16 bytes */
+ // XXX Check for double entries.
+ // Insert the native library.
+ _libraries.insert(std::make_pair(library.get_classloader(), library));
- key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_library->size - 1);
- le = (hashtable_library_loader_entry*) hashtable_library->ptr[slot];
+ _mutex.unlock();
+}
+#endif
- /* search external hash chain for the entry */
- while (le) {
- if (le->loader == loader)
- break;
+/**
+ * Checks if the given native library is loaded.
+ *
+ * @param library Native library.
+ *
+ * @return true if loaded, false otherwise.
+ */
+bool NativeLibraries::is_loaded(NativeLibrary& library)
+{
+ std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
- le = le->hashlink; /* next element in external chain */
- }
+ // No entry for the classloader was found (the range has length
+ // zero).
+ if (its.first == its.second)
+ return false;
+
+ MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
- /* no loader found? return NULL */
+ // No matching entry in the range found.
+ if (it == its.second)
+ return false;
- if (le == NULL)
- return NULL;
+ return true;
+}
- /* search for library name */
- ne = le->namelink;
+/**
+ * Try to find a symbol with the given name in all loaded native
+ * libraries defined by classloader.
+ *
+ * @param symbolname Name of the symbol to find.
+ * @param classloader Defining classloader.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
+{
+ std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
- while (ne) {
- if (ne->name == filename)
- return ne;
+ // No entry for the classloader was found (the range has length
+ // zero).
+ if (its.first == its.second)
+ return NULL;
- ne = ne->hashlink; /* next element in external chain */
- }
+ for (MAP::const_iterator it = its.first; it != its.second; it++) {
+ const NativeLibrary& library = (*it).second;
+ void* symbol = library.resolve_symbol(symbolname);
- /* return entry, if no entry was found, ne is NULL */
+ if (symbol != NULL)
+ return symbol;
+ }
- return ne;
+ return NULL;
}
-#endif
-/* native_library_load *********************************************************
+/**
+ * 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);
- Load a native library and initialize it, if possible.
+ // Insert native agent into list of agents.
+ _agents.push_back(na);
+}
+#endif
- IN:
- name ... name of the library
- cl ..... classloader which loads this library
- RETURN:
- 1 ... library loaded successfully
- 0 ... error
+/**
+ * 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
-*******************************************************************************/
-int native_library_load(JNIEnv *env, utf *name, classloader_t *cl)
+/**
+ * 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()
{
-#if defined(ENABLE_DL)
- void* handle;
-# if defined(ENABLE_JNI)
- void* onload;
- int32_t version;
-# endif
+ // Iterate over all registered agents.
+ for (std::vector<NativeAgent>::iterator it = _agents.begin(); it != _agents.end(); ++it) {
+ NativeAgent& na = *(it);
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
+ // 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");
- /* Is the library already loaded? */
+ char* p = MNEW(char, len);
- if (native_library_find(name, cl) != NULL)
- return 1;
+ os::strcpy(p, NATIVE_LIBRARY_PREFIX);
+ os::strcat(p, na.get_library());
+ os::strcat(p, NATIVE_LIBRARY_SUFFIX);
- /* Open the library. */
+ utf* u = utf_new_char(p);
- handle = native_library_open(name);
+ MFREE(p, char, len);
- if (handle == NULL)
- return 0;
+ // Construct new native library.
+ NativeLibrary nl(u);
-# if defined(ENABLE_JNI)
- /* Resolve JNI_OnLoad function. */
+ // Try to open the library.
+ if (nl.open() == NULL)
+ return false;
- onload = os::dlsym(handle, "JNI_OnLoad");
-
- if (onload != NULL) {
- JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
- JavaVM *vm;
+ // Resolve Agent_OnLoad function.
+ void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
- JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) 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();
- env->GetJavaVM(&vm);
+ Agent_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, char*, void*)) (uintptr_t) onload;
- version = JNI_OnLoad(vm, NULL);
+ jint result = Agent_OnLoad(vm, na.get_options(), NULL);
- /* If the version is not 1.2 and not 1.4 the library cannot be
- loaded. */
+ // Check for error in Agent_OnLoad.
+ if (result != 0) {
+ nl.close();
+ return false;
+ }
+ }
- if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
- os::dlclose(handle);
- return 0;
+ // 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;
}
}
-# endif
-
- /* Insert the library name into the library hash. */
- native_library_add(name, cl, handle);
-
- return 1;
-#else
- vm_abort("native_library_load: not available");
-
- /* Keep compiler happy. */
-
- return 0;
-#endif
+ return true;
}
+#endif
/* native_new_and_init *********************************************************