fprintf/vfprintf dependency fix
[cacao.git] / src / vm / vm.cpp
index 23518fd85435b4100e6971781c716dd0c7f632b0..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.
@@ -69,6 +69,7 @@
 #include "vm/finalizer.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/initialize.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
 #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/profile.hpp"
 #include "vm/jit/optimizing/recompiler.hpp"
 
 #if defined(ENABLE_PYTHON)
 
 #include "vm/jit/trap.hpp"
 
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
 #if defined(ENABLE_VMLOG)
 #include <vmlog_cacao.h>
 #endif
@@ -241,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)
@@ -343,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
@@ -357,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 },
@@ -398,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)");
@@ -434,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)
@@ -471,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);
@@ -554,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.");
@@ -685,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. */
 
@@ -739,7 +718,7 @@ VM::VM(JavaVMInitArgs* vm_args)
           is smaller or equal than the assumption made in
           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));
 
@@ -747,11 +726,6 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        _starttime = builtin_currenttimemillis();
 
-#if defined(ENABLE_JVMTI)
-       /* initialize JVMTI related  **********************************************/
-       jvmti = false;
-#endif
-
        /* iterate over all passed options */
 
        while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
@@ -900,42 +874,34 @@ VM::VM(JavaVMInitArgs* vm_args)
                        break;
 
 #if defined(ENABLE_JVMTI)
-               case OPT_DEBUG:
-                       /* this option exists only for compatibility reasons */
-                       break;
+               case OPT_AGENTLIB:
+                       // Parse option argument.
+                       p = strchr(opt_arg, '=');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-               case OPT_NOAGENT:
-                       /* I don't know yet what Xnoagent should do. This is only for 
-                          compatiblity with eclipse - motse */
+                       _nativeagents.register_agent_library(opt_arg, p);
                        break;
 
-               case OPT_XRUNJDWP:
-                       agentbypath = true;
-                       jvmti       = true;
-                       jdwp        = true;
-
-                       len =
-                               strlen(CACAO_LIBDIR) +
-                               strlen("/libjdwp.so=") +
-                               strlen(opt_arg) +
-                               strlen("0");
-
-                       agentarg = MNEW(char, len);
+               case OPT_AGENTPATH:
+                       // Parse option argument.
+                       p = strchr(opt_arg, '=');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-                       strcpy(agentarg, CACAO_LIBDIR);
-                       strcat(agentarg, "/libjdwp.so=");
-                       strcat(agentarg, &opt_arg[1]);
+                       _nativeagents.register_agent_path(opt_arg, p);
                        break;
 
-               case OPT_AGENTPATH:
-                       agentbypath = true;
+               case OPT_RUN:
+                       // Parse option argument.
+                       p = strchr(opt_arg, ':');
+                       if (p != NULL)
+                               *(p++) = '\0';
 
-               case OPT_AGENTLIB:
-                       jvmti = true;
-                       agentarg = opt_arg;
+                       _nativeagents.register_agent_library(opt_arg, p);
                        break;
 #endif
-                       
+
                case OPT_MX:
                case OPT_MS:
                case OPT_SS:
@@ -1284,18 +1250,6 @@ VM::VM(JavaVMInitArgs* vm_args)
        if (opt_PrintConfig)
                print_run_time_config();
 
-#if defined(ENABLE_JVMTI)
-       if (jvmti) {
-               jvmti_set_phase(JVMTI_PHASE_ONLOAD);
-               jvmti_agentload(agentarg, agentbypath, &handle, &libname);
-
-               if (jdwp)
-                       MFREE(agentarg, char, strlen(agentarg));
-
-               jvmti_set_phase(JVMTI_PHASE_PRIMORDIAL);
-       }
-#endif
-
        /* initialize the garbage collector */
 
        gc_init(opt_heapmaxsize, opt_heapstartsize);
@@ -1330,6 +1284,15 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        utf8_init();
 
+       // Hook point before the VM is initialized.
+       Hook::vm_preinit();
+
+#if defined(ENABLE_JVMTI)
+       // AFTER: utf8_init
+       if (!_nativeagents.load_agents())
+               os::abort("vm_create: load_agents failed");
+#endif
+
        /* AFTER: thread_preinit */
 
        _suckclasspath.add_from_property("java.endorsed.dirs");
@@ -1478,17 +1441,6 @@ VM::VM(JavaVMInitArgs* vm_args)
 # endif
 #endif
 
-#if defined(ENABLE_JVMTI)
-# if defined(ENABLE_GC_CACAO)
-       /* XXX this will not work with the new indirection cells for classloaders!!! */
-       assert(0);
-# endif
-       if (jvmti) {
-               /* add agent library to native library hashtable */
-               native_hashtable_library_add(utf_new_char(libname), class_java_lang_Object->classloader, handle);
-       }
-#endif
-
        /* Increment the number of VMs. */
 
        vms++;
@@ -1496,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");
 }
 
 
@@ -1509,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__)
@@ -1569,6 +1531,60 @@ void VM::print_run_time_config()
 }
 
 
+/**
+ * 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.
@@ -1719,21 +1735,6 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
        typeinfo_test();
 #endif
 
-#if defined(ENABLE_JVMTI)
-       jvmti_set_phase(JVMTI_PHASE_LIVE);
-#endif
-
-       /* set ThreadMXBean variables */
-
-//     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
-//     _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.get_handle());
@@ -1788,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. */
 
@@ -1812,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);
@@ -2011,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();
@@ -2506,11 +2512,7 @@ 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, ...)
 {