* src/vm/hook.hpp: Added new file for hook points.
[cacao.git] / src / native / native.cpp
index 794fffbe2edcdf9ef1e4d9bf1b595e4a5d3cbc01..e5e2c7c6272ec3aae80fce5c56006960ea78f5c2 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 *********************************************
 
@@ -398,109 +309,68 @@ static utf *native_method_symbol(utf *classname, utf *methodname)
 }
 
 
-/* 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);
@@ -511,150 +381,133 @@ functionptr native_method_resolve(methodinfo *m)
 
        /* 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_print("NativeLibrary::open: os::dlopen failed: ");
+                       log_print(os::dlerror());
                        log_finish();
                }
 
@@ -664,259 +517,314 @@ void* native_library_open(utf *filename)
        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_verbosejni)
+                       printf("failed ]\n");
+
                if (opt_verbose) {
                        log_start();
-                       log_print("native_library_close: os::dlclose failed: ");
-                       log_print(dlerror());
+                       log_print("NativeLibrary::close: os::dlclose failed: ");
+                       log_print(os::dlerror());
                        log_finish();
                }
        }
+
+       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 */
+       // Is the library already loaded?
+       if (is_loaded())
+               return true;
 
-       if (le == NULL) {
-               le = NEW(hashtable_library_loader_entry);
+       // Open the library.
+       open();
 
-               le->loader   = loader;
-               le->namelink = NULL;
+       if (_handle == NULL)
+               return false;
 
-               /* insert entry into hashtable */
-
-               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;
+
+       return true;
+}
 
-       if (le == NULL)
-               return NULL;
 
-       /* search for library name */
+/**
+ * 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);
 
-       ne = le->namelink;
+       // No entry for the classloader was found (the range has length
+       // zero).
+       if (its.first == its.second)
+               return NULL;
 
-       while (ne) {
-               if (ne->name == filename)
-                       return ne;
+       for (MAP::const_iterator it = its.first; it != its.second; it++) {
+               const NativeLibrary& library = (*it).second;
+               void* symbol = library.resolve_symbol(symbolname);
 
-               ne = ne->hashlink;                  /* next element in external chain */
+               if (symbol != NULL)
+                       return symbol;
        }
 
-       /* return entry, if no entry was found, ne is NULL */
-
-       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");
+               // Resolve Agent_OnLoad function.
+               void* onload = os::dlsym(nl.get_handle(), "Agent_OnLoad");
 
-       if (onload != NULL) {
-               JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
-               JavaVM *vm;
-
-               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 *********************************************************