fprintf/vfprintf dependency fix
[cacao.git] / src / vm / vm.cpp
index afdbdc97c013c101e0bf530b3edac6ce75a6f862..ef1e93dbcdba2d659f596b7ee0872a423f06820c 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/vm.cpp - VM startup and shutdown functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include "mm/codememory.h"
 #include "mm/dumpmemory.hpp"
 #include "mm/gc.hpp"
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
 #include "native/jni.hpp"
 #include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
 
-#include "native/vm/nativevm.h"
+#include "native/vm/nativevm.hpp"
 
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 
-#include "vm/array.h"
+#include "vm/array.hpp"
 
 #if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
 #endif
 
 #include "vm/jit/builtin.hpp"
-#include "vm/classcache.h"
+#include "vm/classcache.hpp"
 #include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
+#include "vm/finalizer.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
-#include "vm/initialize.h"
+#include "vm/hook.hpp"
+#include "vm/initialize.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
 #include "vm/primitive.hpp"
-#include "vm/properties.h"
-#include "vm/signallocal.h"
+#include "vm/properties.hpp"
+#include "vm/signallocal.hpp"
 #include "vm/statistics.h"
 #include "vm/string.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
 #include "vm/vm.hpp"
 
-#include "vm/jit/argument.h"
+#include "vm/jit/argument.hpp"
 #include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
 
 #if defined(ENABLE_DISASSEMBLER)
 # include "vm/jit/disass.h"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/methodtree.h"
 
-#if defined(ENABLE_PROFILING)
-# include "vm/jit/optimizing/profile.h"
-#endif
-
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/profile.hpp"
+#include "vm/jit/optimizing/recompiler.hpp"
 
 #if defined(ENABLE_PYTHON)
 # include "vm/jit/python.h"
 #endif
 
-#include "vm/jit/trap.h"
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_VMLOG)
 #include <vmlog_cacao.h>
@@ -190,10 +183,11 @@ enum {
        OPT_MS,
        OPT_MX,
 
+       OPT_XCHECK_JNI,
+
        /* CACAO options */
 
        OPT_VERBOSE1,
-       OPT_NOIEEE,
 
 #if defined(ENABLE_STATISTICS)
        OPT_TIME,
@@ -206,14 +200,10 @@ enum {
        OPT_SHOW,
        OPT_DEBUGCOLOR,
 
-#if !defined(NDEBUG)
-       OPT_ALL,
-       OPT_METHOD,
-       OPT_SIGNATURE,
-#endif
-
 #if defined(ENABLE_VERIFIER)
        OPT_NOVERIFY,
+       OPT_XVERIFY_ALL,
+       OPT_XVERIFY_NONE,
 #if defined(TYPECHECK_VERBOSE)
        OPT_VERBOSETC,
 #endif
@@ -245,12 +235,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)
@@ -306,7 +294,8 @@ opt_struct opts[] = {
        { "noasyncgc",         false, OPT_IGNORE },
 #if defined(ENABLE_VERIFIER)
        { "noverify",          false, OPT_NOVERIFY },
-       { "Xverify:none",      false, OPT_NOVERIFY },
+       { "Xverify:all",       false, OPT_XVERIFY_ALL },
+       { "Xverify:none",      false, OPT_XVERIFY_NONE },
 #endif
        { "v",                 false, OPT_VERBOSE1 },
        { "verbose:",          true,  OPT_VERBOSE },
@@ -314,9 +303,6 @@ opt_struct opts[] = {
 #if defined(ENABLE_VERIFIER) && defined(TYPECHECK_VERBOSE)
        { "verbosetc",         false, OPT_VERBOSETC },
 #endif
-#if defined(__ALPHA__)
-       { "noieee",            false, OPT_NOIEEE },
-#endif
 #if defined(ENABLE_STATISTICS)
        { "time",              false, OPT_TIME },
        { "stat",              false, OPT_STAT },
@@ -325,11 +311,6 @@ opt_struct opts[] = {
        { "c",                 true,  OPT_CHECK },
        { "l",                 false, OPT_LOAD },
 
-#if !defined(NDEBUG)
-       { "all",               false, OPT_ALL },
-       { "sig",               true,  OPT_SIGNATURE },
-#endif
-
 #if defined(ENABLE_LOOP)
        { "oloop",             false, OPT_OLOOP },
 #endif
@@ -354,7 +335,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
@@ -368,11 +349,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 },
@@ -381,6 +362,8 @@ opt_struct opts[] = {
        { "Xss",               true,  OPT_SS },
        { "ss",                true,  OPT_SS },
 
+       { "Xcheck:jni",        false, OPT_XCHECK_JNI },
+
 #if defined(ENABLE_PROFILING)
        { "Xprof:",            true,  OPT_PROF_OPTION },
        { "Xprof",             false, OPT_PROF },
@@ -388,10 +371,6 @@ opt_struct opts[] = {
 
        /* keep these at the end of the list */
 
-#if !defined(NDEBUG)
-       { "m",                 true,  OPT_METHOD },
-#endif
-
        { "s",                 true,  OPT_SHOW },
        { "debug-color",      false,  OPT_DEBUGCOLOR },
 
@@ -411,7 +390,7 @@ opt_struct opts[] = {
 
 *******************************************************************************/
 
-void usage(void)
+static void usage(void)
 {
        puts("Usage: cacao [-options] classname [arguments]");
        puts("               (to run a class file)");
@@ -447,16 +426,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)
@@ -484,14 +465,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);
@@ -509,9 +482,6 @@ static void XXusage(void)
 #ifdef TYPECHECK_VERBOSE
        puts("    -verbosetc               write debug messages while typechecking");
 #endif
-#if defined(__ALPHA__)
-       puts("    -noieee                  don't use ieee compliant arithmetic");
-#endif
 #if defined(ENABLE_VERIFIER)
        puts("    -noverify                don't verify classfiles");
 #endif
@@ -526,11 +496,6 @@ static void XXusage(void)
        puts("    -oloop                   optimize array accesses in loops");
 #endif
        puts("    -l                       don't start the class after loading");
-#if !defined(NDEBUG)
-       puts("    -all                     compile all methods, no execution");
-       puts("    -m                       compile only a specific method");
-       puts("    -sig                     specify signature for a specific method");
-#endif
 
        puts("    -s...                    show...");
        puts("      (c)onstants            the constant pool");
@@ -575,9 +540,9 @@ static void XXusage(void)
 static void version(bool opt_exit)
 {
        puts("java version \""JAVA_VERSION"\"");
-       puts("CACAO version "VERSION"\n");
+       puts("CACAO version "VERSION_FULL"\n");
 
-       puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+       puts("Copyright (C) 1996-2005, 2006, 2007, 2008, 2009, 2010, 2011");
        puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
        puts("This is free software; see the source for copying conditions.  There is NO");
        puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
@@ -706,13 +671,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. */
 
@@ -728,24 +686,17 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* Install the exit handler. */
 
        if (atexit(vm_exit_handler))
-               VM::get_current()->abort("atexit failed: %s\n", strerror(errno));
+               os::abort("atexit failed: %s\n", strerror(errno));
 
        /* Set some options. */
 
        opt_version       = false;
        opt_exit          = false;
 
-       opt_noieee        = false;
-
        opt_heapmaxsize   = HEAP_MAXSIZE;
        opt_heapstartsize = HEAP_STARTSIZE;
        opt_stacksize     = STACK_SIZE;
 
-       /* Initialize the properties list before command-line handling.
-          Otherwise -XX:+PrintConfig crashes. */
-
-       properties_init();
-
        // First of all, parse the -XX options.
 
 #if defined(ENABLE_VMLOG)
@@ -765,9 +716,9 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        /* We need to check if the actual size of a java.lang.Class object
           is smaller or equal than the assumption made in
-          src/vm/class.h. */
+          src/vm/class.hpp. */
 
-#warning FIXME We need to check the size of java.lang.Class!!!
+// FIXME We need to check the size of java.lang.Class!!!
 //     if (sizeof(java_lang_Class) > sizeof(dummy_java_lang_Class))
 //             vm_abort("vm_create: java_lang_Class structure is bigger than classinfo.object (%d > %d)", sizeof(java_lang_Class), sizeof(dummy_java_lang_Class));
 
@@ -775,15 +726,6 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        _starttime = builtin_currenttimemillis();
 
-#if defined(ENABLE_JVMTI)
-       /* initialize JVMTI related  **********************************************/
-       jvmti = false;
-#endif
-
-       /* Fill the properties before command-line handling. */
-
-       properties_set();
-
        /* iterate over all passed options */
 
        while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
@@ -818,14 +760,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                           classpath. */
 
                        // FIXME Make class_path const char*.
-                       class_path = (char*) properties_get("java.class.path");
+                       class_path = (char*) _properties.get("java.class.path");
 
                        p = MNEW(char, strlen(opt_arg) + strlen("0"));
 
                        strcpy(p, opt_arg);
 
 #if defined(ENABLE_JAVASE)
-                       properties_add("java.class.path", p);
+                       _properties.put("java.class.path", p);
 #endif
 
                        MFREE(class_path, char, strlen(class_path));
@@ -835,14 +777,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                        for (unsigned int i = 0; i < strlen(opt_arg); i++) {
                                if (opt_arg[i] == '=') {
                                        opt_arg[i] = '\0';
-                                       properties_add(opt_arg, opt_arg + i + 1);
+                                       _properties.put(opt_arg, opt_arg + i + 1);
                                        goto opt_d_done;
                                }
                        }
 
                        /* if no '=' is given, just create an empty property */
 
-                       properties_add(opt_arg, "");
+                       _properties.put(opt_arg, "");
 
                opt_d_done:
                        break;
@@ -852,14 +794,14 @@ VM::VM(JavaVMInitArgs* vm_args)
                           new boot classpath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        p = MNEW(char, strlen(opt_arg) + strlen("0"));
 
                        strcpy(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, strlen(boot_class_path));
                        break;
@@ -868,7 +810,7 @@ VM::VM(JavaVMInitArgs* vm_args)
                        /* Append to bootclasspath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len = strlen(boot_class_path);
 
@@ -882,15 +824,15 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
                        break;
 
                case OPT_BOOTCLASSPATH_P:
                        /* Prepend to bootclasspath. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len = strlen(boot_class_path);
 
@@ -900,8 +842,8 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, boot_class_path);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, len);
                        break;
@@ -911,7 +853,7 @@ VM::VM(JavaVMInitArgs* vm_args)
                           classes. */
 
                        // FIXME Make boot_class_path const char*.
-                       boot_class_path = (char*) properties_get("sun.boot.class.path");
+                       boot_class_path = (char*) _properties.get("sun.boot.class.path");
 
                        len =
                                strlen(CACAO_VM_ZIP) +
@@ -925,49 +867,41 @@ VM::VM(JavaVMInitArgs* vm_args)
                        strcat(p, ":");
                        strcat(p, opt_arg);
 
-                       properties_add("sun.boot.class.path", p);
-                       properties_add("java.boot.class.path", p);
+                       _properties.put("sun.boot.class.path", p);
+                       _properties.put("java.boot.class.path", p);
 
                        MFREE(boot_class_path, char, strlen(boot_class_path));
                        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:
@@ -995,6 +929,10 @@ VM::VM(JavaVMInitArgs* vm_args)
                        }
                        break;
 
+               case OPT_XCHECK_JNI:
+                       // HotSpot compatibility option.
+                       break;
+
                case OPT_VERBOSE1:
                        opt_verbose = true;
                        break;
@@ -1046,12 +984,13 @@ VM::VM(JavaVMInitArgs* vm_args)
                        opt_version = true;
                        break;
 
-               case OPT_NOIEEE:
-                       opt_noieee = true;
+#if defined(ENABLE_VERIFIER)
+               case OPT_XVERIFY_ALL:
+                       opt_verify = true;
                        break;
 
-#if defined(ENABLE_VERIFIER)
                case OPT_NOVERIFY:
+               case OPT_XVERIFY_NONE:
                        opt_verify = false;
                        break;
 #endif
@@ -1091,24 +1030,6 @@ VM::VM(JavaVMInitArgs* vm_args)
                        makeinitializations = false;
                        break;
 
-#if !defined(NDEBUG)
-               case OPT_ALL:
-                       compileall = true;
-                       opt_run = false;
-                       makeinitializations = false;
-                       break;
-
-               case OPT_METHOD:
-                       opt_run = false;
-                       opt_method = opt_arg;
-                       makeinitializations = false;
-                       break;
-
-               case OPT_SIGNATURE:
-                       opt_signature = opt_arg;
-                       break;
-#endif
-
                case OPT_SHOW:       /* Display options */
                        for (unsigned int i = 0; i < strlen(opt_arg); i++) {            
                                switch (opt_arg[i]) {
@@ -1329,27 +1250,11 @@ 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);
 
 #if defined(ENABLE_THREADS)
-       /* BEFORE: threads_preinit */
-
-       threadlist_init();
-
        /* AFTER: gc_init */
 
        threads_preinit();
@@ -1359,7 +1264,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* install architecture dependent signal handlers */
 
        if (!signal_init())
-               VM::get_current()->abort("vm_create: signal_init failed");
+               os::abort("vm_create: signal_init failed");
 
 #if defined(ENABLE_INTRP)
        /* Allocate main thread stack on the Java heap. */
@@ -1373,18 +1278,24 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* AFTER: threads_preinit */
 
        if (!string_init())
-               VM::get_current()->abort("vm_create: string_init failed");
+               os::abort("vm_create: string_init failed");
 
        /* AFTER: threads_preinit */
 
        utf8_init();
 
-       /* AFTER: thread_preinit */
+       // Hook point before the VM is initialized.
+       Hook::vm_preinit();
 
-       if (!suck_init())
-               VM::get_current()->abort("vm_create: suck_init failed");
+#if defined(ENABLE_JVMTI)
+       // AFTER: utf8_init
+       if (!_nativeagents.load_agents())
+               os::abort("vm_create: load_agents failed");
+#endif
+
+       /* AFTER: thread_preinit */
 
-       suck_add_from_property("java.endorsed.dirs");
+       _suckclasspath.add_from_property("java.endorsed.dirs");
 
        /* Now we have all options handled and we can print the version
           information.
@@ -1397,14 +1308,14 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* AFTER: utf8_init */
 
        // FIXME Make boot_class_path const char*.
-       boot_class_path = (char*) properties_get("sun.boot.class.path");
-       suck_add(boot_class_path);
+       boot_class_path = (char*) _properties.get("sun.boot.class.path");
+       _suckclasspath.add(boot_class_path);
 
        /* initialize the classcache hashtable stuff: lock, hashtable
           (must be done _after_ threads_preinit) */
 
        if (!classcache_init())
-               VM::get_current()->abort("vm_create: classcache_init failed");
+               os::abort("vm_create: classcache_init failed");
 
        /* Initialize the code memory management. */
        /* AFTER: threads_preinit */
@@ -1415,7 +1326,7 @@ VM::VM(JavaVMInitArgs* vm_args)
           threads_preinit) */
 
        if (!finalizer_init())
-               VM::get_current()->abort("vm_create: finalizer_init failed");
+               os::abort("vm_create: finalizer_init failed");
 
        /* Initialize the JIT compiler. */
 
@@ -1447,13 +1358,7 @@ VM::VM(JavaVMInitArgs* vm_args)
 #endif
 
        if (!builtin_init())
-               VM::get_current()->abort("vm_create: builtin_init failed");
-
-       /* Initialize the native subsystem. */
-       /* BEFORE: threads_init */
-
-       if (!native_init())
-               VM::get_current()->abort("vm_create: native_init failed");
+               os::abort("vm_create: builtin_init failed");
 
        /* Register the native methods implemented in the VM. */
        /* BEFORE: threads_init */
@@ -1466,7 +1371,7 @@ VM::VM(JavaVMInitArgs* vm_args)
           (e.g. NewGlobalRef). */
 
        if (!jni_init())
-               VM::get_current()->abort("vm_create: jni_init failed");
+               os::abort("vm_create: jni_init failed");
 #endif
 
 #if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
@@ -1474,7 +1379,7 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* BEFORE: threads_init */
 
        if (!localref_table_init())
-               VM::get_current()->abort("vm_create: localref_table_init failed");
+               os::abort("vm_create: localref_table_init failed");
 #endif
 
        /* Iinitialize some important system classes. */
@@ -1489,21 +1394,17 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* Initialize the native VM subsystem. */
        /* AFTER: threads_init (at least for SUN's classes) */
 
-       nativevm_init();
+       if (!nativevm_init())
+               os::abort("vm_create: nativevm_init failed");
 
 #if defined(ENABLE_PROFILING)
        /* initialize profiling */
 
        if (!profile_init())
-               VM::get_current()->abort("vm_create: profile_init failed");
+               os::abort("vm_create: profile_init failed");
 #endif
 
 #if defined(ENABLE_THREADS)
-       /* initialize recompilation */
-
-       if (!recompile_init())
-               VM::get_current()->abort("vm_create: recompile_init failed");
-
        /* start the signal handler thread */
 
 #if defined(__LINUX__)
@@ -1511,45 +1412,33 @@ VM::VM(JavaVMInitArgs* vm_args)
        if (threads_pthreads_implementation_nptl)
 #endif
                if (!signal_start_thread())
-                       VM::get_current()->abort("vm_create: signal_start_thread failed");
+                       os::abort("vm_create: signal_start_thread failed");
 
        /* finally, start the finalizer thread */
 
        if (!finalizer_start_thread())
-               VM::get_current()->abort("vm_create: finalizer_start_thread failed");
+               os::abort("vm_create: finalizer_start_thread failed");
 
 # if !defined(NDEBUG)
        /* start the memory profiling thread */
 
        if (opt_ProfileMemoryUsage || opt_ProfileGCMemoryUsage)
                if (!memory_start_thread())
-                       VM::get_current()->abort("vm_create: memory_start_thread failed");
+                       os::abort("vm_create: memory_start_thread failed");
 # endif
 
-       /* start the recompilation thread (must be done before the
-          profiling thread) */
-
-       if (!recompile_start_thread())
-               VM::get_current()->abort("vm_create: recompile_start_thread failed");
+       // Start the recompilation thread (must be done before the
+       // profiling thread).
+       // FIXME Only works for one recompiler.
+       _recompiler.start();
 
 # if defined(ENABLE_PROFILING)
        /* start the profile sampling thread */
 
 /*     if (opt_prof) */
 /*             if (!profile_start_thread()) */
-/*                     VM::get_current()->abort("vm_create: profile_start_thread failed"); */
-# 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);
+/*                     os::abort("vm_create: profile_start_thread failed"); */
 # 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. */
@@ -1559,11 +1448,21 @@ VM::VM(JavaVMInitArgs* vm_args)
        // Initialization is done, VM is created.
        _created      = true;
        _initializing = false;
-       
+
+       // Set the VM inittime.
+       _inittime = builtin_currenttimemillis();
+
+       // Hook point after the VM is initialized.
+       Hook::vm_init();
+
        // Print the run-time VM configuration after all stuff is set and
        // the VM is initialized.
        if (opt_PrintConfig)
                print_run_time_config();
+
+       // Start runtime agents after the VM is created.
+       if (!start_runtime_agents())
+               os::abort("vm_create: start_runtime_agents failed");
 }
 
 
@@ -1572,7 +1471,7 @@ VM::VM(JavaVMInitArgs* vm_args)
  */
 void VM::print_build_time_config(void)
 {
-       puts("CACAO "VERSION" configure/build options:");
+       puts("CACAO "VERSION_FULL" configure/build options:");
        puts("");
        puts("  ./configure: "VERSION_CONFIGURE_ARGS"");
 #if defined(__VERSION__)
@@ -1612,7 +1511,7 @@ void VM::print_build_time_config(void)
 /**
  * Print run-time VM configuration.
  */
-void VM::print_run_time_config(void)
+void VM::print_run_time_config()
 {
        puts("Run-time variables:\n");
        printf("  maximum heap size              : %d\n", opt_heapmaxsize);
@@ -1620,18 +1519,72 @@ void VM::print_run_time_config(void)
        printf("  stack size                     : %d\n", opt_stacksize);
 
 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-       printf("  gnu.classpath.boot.library.path: %s\n", properties_get("gnu.classpath.boot.library.path"));
+       printf("  gnu.classpath.boot.library.path: %s\n", _properties.get("gnu.classpath.boot.library.path"));
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-       printf("  sun.boot.library.path          : %s\n", properties_get("sun.boot.library.path"));
+       printf("  sun.boot.library.path          : %s\n", _properties.get("sun.boot.library.path"));
 #endif
 
-       printf("  java.boot.class.path           : %s\n", properties_get("java.boot.class.path"));
-       printf("  java.class.path                : %s\n", properties_get("java.class.path"));
+       printf("  java.boot.class.path           : %s\n", _properties.get("java.boot.class.path"));
+       printf("  java.class.path                : %s\n", _properties.get("java.class.path"));
 
        puts("");
 }
 
 
+/**
+ * Start runtime agents which are provided by the JRE but need to be
+ * started explicitly by the VM.
+ */
+bool VM::start_runtime_agents()
+{
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       // Nothing to do.
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       // Check whether the management agent should be loaded.
+       if ((_properties.get("com.sun.management.jmxremote") != NULL) ||
+               (_properties.get("com.sun.management.snmp") != NULL))
+       {
+
+               // Load the management agent class.
+               classinfo* class_sun_management_Agent;
+               if (!(class_sun_management_Agent = load_class_from_sysloader(utf_new_char("sun/management/Agent"))))
+                       return false;
+
+               // Link the management agent class.
+               if (!link_class(class_sun_management_Agent))
+                       return false;
+
+               // Actually start the management agent.
+               methodinfo* m = class_resolveclassmethod(class_sun_management_Agent,
+                                                                                                utf_new_char("startAgent"),
+                                                                                                utf_void__void,
+                                                                                                class_java_lang_Object,
+                                                                                                false);
+
+               if (m == NULL)
+                       return false;
+
+               (void) vm_call_method(m, NULL);
+
+               if (exceptions_get_exception() != NULL)
+                       return false;
+       }
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+       // Nothing to do.
+
+#else
+# error unknown classpath configuration
+#endif
+
+       return true;
+}
+
+
 /* vm_run **********************************************************************
 
    Runs the main-method of the passed class.
@@ -1640,32 +1593,19 @@ void VM::print_run_time_config(void)
 
 void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
 {
-       char*                      option;
-       char*                      mainname;
-       char*                      p;
-       utf                       *mainutf;
-       classinfo                 *mainclass;
-       java_handle_t             *e;
-       methodinfo                *m;
-       java_handle_objectarray_t *oa; 
-       s4                         oalength;
-       utf                       *u;
-       java_handle_t             *s;
-       int                        status;
-
-       // Prevent compiler warnings.
-       oa = NULL;
+       methodinfo* m;
+       int         status;
 
 #if !defined(NDEBUG)
-       if (compileall) {
+       if (opt_CompileAll) {
                vm_compile_all();
                return;
        }
 #endif
 
-       /* Get the main class plus it's arguments. */
+       /* Get the main class or jar file argument. */
 
-       mainname = NULL;
+       char* mainname = NULL;
 
        if (opt_index < vm_args->nOptions) {
                /* Get main-class argument. */
@@ -1676,12 +1616,12 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                   classpath. */
 
                if (opt_jar == true) {
-                       p = MNEW(char, strlen(mainname) + strlen("0"));
+                       char* p = MNEW(char, strlen(mainname) + strlen("0"));
 
                        strcpy(p, mainname);
 
 #if defined(ENABLE_JAVASE)
-                       properties_add("java.class.path", p);
+                       VM::get_current()->get_properties().put("java.class.path", p);
 #endif
                }
                else {
@@ -1692,22 +1632,9 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                                        mainname[i] = '/';
                }
 
-               /* Build argument array.  Move index to first argument. */
+               /* Move index to first argument. */
 
                opt_index++;
-
-               oalength = vm_args->nOptions - opt_index;
-
-               oa = builtin_anewarray(oalength, class_java_lang_String);
-
-               for (int i = 0; i < oalength; i++) {
-                       option = vm_args->options[opt_index + i].optionString;
-
-                       u = utf_new_char(option);
-                       s = javastring_new(u);
-
-                       array_objectarray_element_set(oa, i, s);
-               }
        }
 
        /* Do we have a main-class argument? */
@@ -1716,12 +1643,30 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                usage();
 
 #if !defined(NDEBUG)
-       if (opt_method != NULL) {
+       if (opt_CompileMethod != NULL) {
                vm_compile_method(mainname);
                return;
        }
 #endif
 
+       /* Build argument array. */
+
+       int32_t oalength = vm_args->nOptions - opt_index;
+
+       ObjectArray oa(oalength, class_java_lang_String);
+
+       if (oa.is_null())
+               vm_exit(1);
+
+       for (int i = 0; i < oalength; i++) {
+               char* option = vm_args->options[opt_index + i].optionString;
+
+               utf*           u = utf_new_char(option);
+               java_handle_t* s = javastring_new(u);
+
+               oa.set_element(i, s);
+       }
+
        /* set return value to OK */
 
        status = 0;
@@ -1737,17 +1682,17 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
 
        /* load the main class */
 
-       mainutf = utf_new_char(mainname);
+       utf* mainutf = utf_new_char(mainname);
 
 #if defined(ENABLE_JAVAME_CLDC1_1)
-       mainclass = load_class_bootstrap(mainutf);
+       classinfo* mainclass = load_class_bootstrap(mainutf);
 #else
-       mainclass = load_class_from_sysloader(mainutf);
+       classinfo* mainclass = load_class_from_sysloader(mainutf);
 #endif
 
        /* error loading class */
 
-       e = exceptions_get_and_clear_exception();
+       java_handle_t* e = exceptions_get_and_clear_exception();
 
        if ((e != NULL) || (mainclass == NULL)) {
                exceptions_throw_noclassdeffounderror_cause(e);
@@ -1790,24 +1735,9 @@ 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++;
-//     _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
-
-//     if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
-//             _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
-//             _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
-//                     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-#warning Move to C++
-
        /* start the main thread */
 
-       (void) vm_call_method(m, NULL, oa);
+       (void) vm_call_method(m, NULL, oa.get_handle());
 
        /* exception occurred? */
 
@@ -1821,7 +1751,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
           the application's main method exits. */
 
        if (!thread_detach_current_thread())
-               VM::get_current()->abort("vm_run: Could not detach main thread.");
+               os::abort("vm_run: Could not detach main thread.");
 #endif
 
        /* Destroy the JavaVM. */
@@ -1859,10 +1789,12 @@ int vm_destroy(JavaVM *vm)
        threads_join_all_threads();
 #endif
 
+       // Hook point before the VM is actually destroyed.
+       Hook::vm_shutdown();
+
        /* VM is gone. */
 
 //     _created = false;
-#warning Move to C++
 
        /* Everything is ok. */
 
@@ -1883,7 +1815,6 @@ void vm_exit(s4 status)
        /* signal that we are exiting */
 
 //     _exiting = true;
-#warning Move to C++
 
        assert(class_java_lang_System);
        assert(class_java_lang_System->state & CLASS_LOADED);
@@ -2019,78 +1950,6 @@ void vm_exit_handler(void)
 }
 
 
-/**
- * Prints an error message and aborts the VM.
- *
- * @param text Error message to print.
- */
-void VM::abort(const char* text, ...)
-{
-       va_list ap;
-
-       // Print the log message.
-       log_start();
-
-       va_start(ap, text);
-       log_vprint(text, ap);
-       va_end(ap);
-
-       log_finish();
-
-       // Print a backtrace.
-       os::print_backtrace();
-
-       // Now abort the VM.
-       os::abort();
-}
-
-
-/**
- * Prints an error message, appends ":" plus the strerror-message of
- * errnum and aborts the VM.
- *
- * @param errnum Error number.
- * @param text   Error message to print.
- */
-void VM::abort_errnum(int errnum, const char* text, ...)
-{
-       va_list ap;
-
-       // Print the log message.
-       log_start();
-
-       va_start(ap, text);
-       log_vprint(text, ap);
-       va_end(ap);
-
-       // Print the strerror-message of errnum.
-       log_print(": %s", os::strerror(errnum));
-
-       log_finish();
-
-       // Print a backtrace.
-       os::print_backtrace();
-
-       // Now abort the VM.
-       os::abort();
-}
-
-
-/**
- * Equal to VM::abort_errnum, but uses errno to get the error number.
- *
- * @param text Error message to print.
- */
-void VM::abort_errno(const char* text, ...)
-{
-       va_list ap;
-
-       va_start(ap, text);
-       abort_errnum(errno, text, ap);
-       va_end(ap);
-}
-
-
 /* vm_abort_disassemble ********************************************************
 
    Prints an error message, disassemble the given code range (if
@@ -2137,7 +1996,7 @@ void vm_abort_disassemble(void *pc, int count, const char *text, ...)
                pc = disassinstr((u1*) pc);
 #endif
 
-       VM::get_current()->abort("Aborting...");
+       os::abort("Aborting...");
 }
 
 
@@ -2154,7 +2013,11 @@ static char *vm_get_mainclass_from_jar(char *mainname)
        methodinfo    *m;
        java_handle_t *s;
 
+#if defined(ENABLE_JAVAME_CLDC1_1)
+       c = load_class_bootstrap(utf_new_char("java/util/jar/JarFile"));
+#else
        c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
+#endif
 
        if (c == NULL) {
                exceptions_print_stacktrace();
@@ -2362,24 +2225,24 @@ static void vm_compile_method(char* mainname)
        if (!link_class(mainclass))
                exceptions_print_stacktrace();
 
-       if (opt_signature != NULL) {
+       if (opt_CompileSignature != NULL) {
                m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char(opt_method),
-                                                                        utf_new_char(opt_signature),
+                                                                        utf_new_char(opt_CompileMethod),
+                                                                        utf_new_char(opt_CompileSignature),
                                                                         mainclass,
                                                                         false);
        }
        else {
                m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char(opt_method),
+                                                                        utf_new_char(opt_CompileMethod),
                                                                         NULL,
                                                                         mainclass,
                                                                         false);
        }
 
        if (m == NULL)
-               VM::get_current()->abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
-                                opt_method, opt_signature ? opt_signature : "");
+               os::abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+                                opt_CompileMethod, opt_CompileSignature ? opt_CompileSignature : "");
                
        jit_compile(m);
 }
@@ -2617,7 +2480,7 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
                break;
 
        default:
-               VM::get_current()->abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
+               os::abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
        }
 
        /* enter the nativeworld again */
@@ -2649,37 +2512,28 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
 extern "C" {
 
-JavaVM* VM_get_javavm()      { return VM::get_current()->get_javavm(); }
 JNIEnv* VM_get_jnienv()      { return VM::get_current()->get_jnienv(); }
-bool    VM_is_initializing() { return VM::get_current()->is_initializing(); }
-bool    VM_is_created()      { return VM::get_current()->is_created(); }
-int64_t VM_get_starttime()   { return VM::get_current()->get_starttime(); }
 
 void vm_abort(const char* text, ...)
 {
        va_list ap;
 
-       va_start(ap, text);
-       VM::get_current()->abort(text, ap);
-       va_end(ap);
-}
+       log_println("vm_abort: WARNING, port me to C++ and use os::abort() instead.");
 
-void vm_abort_errnum(int errnum, const char* text, ...)
-{
-       va_list ap;
+       // Print the log message.
+       log_start();
 
        va_start(ap, text);
-       VM::get_current()->abort_errnum(errnum, text, ap);
+       log_vprint(text, ap);
        va_end(ap);
-}
 
-void vm_abort_errno(const char* text, ...)
-{
-       va_list ap;
+       log_finish();
 
-       va_start(ap, text);
-       VM::get_current()->abort_errno(text, ap);
-       va_end(ap);
+       // Print a backtrace.
+       os::print_backtrace();
+
+       // Now abort the VM.
+       os::abort();
 }
 
 }