src/vm/vm.c(usage): added information for jvmti agent for jdwp
[cacao.git] / src / cacao / cacao.c
index 0eb0e4c69c41c16dc88c4c98a608a3bd96bdd06e..19bfeccdfdc7f7d8016cadb0ad5e3f9aededb20d 100644 (file)
@@ -1,10 +1,9 @@
-/* cacao/cacao.c - contains main() of cacao
+/* src/cacao/cacao.c - contains main() of cacao
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Institut f. Computersprachen, TU Wien
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
-   S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
-   J. Wenninger
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Reinhard Grafl
 
    Changes: Andi Krall
             Mark Probst
             Philipp Tomsich
+            Christian Thalinger
 
-   This module does the following tasks:
-     - Command line option handling
-     - Calling initialization routines
-     - Calling the class loader
-     - Running the main method
-
-   $Id: cacao.c 1621 2004-11-30 13:06:55Z twisti $
+   $Id: cacao.c 4954 2006-05-25 21:59:49Z motse $
 
 */
 
 
+#include "config.h"
+
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "cacao/cacao.h"
-#include "mm/boehm.h"
-#include "mm/memory.h"
-#include "native/native.h"
+#include "vm/types.h"
+
+#include "native/jni.h"
+#include "native/include/java_lang_String.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/jvmti.h"
+#include "native/jvmti/cacaodbg.h"
+
+#if defined(ENABLE_THREADS)
+#include <pthread.h>
+#endif
+#endif
+
 #include "toolbox/logging.h"
+#include "vm/classcache.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/loader.h"
 #include "vm/options.h"
 #include "vm/statistics.h"
-#include "vm/tables.h"
+#include "vm/stringlocal.h"
+#include "vm/suck.h"
+#include "vm/vm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 
 #ifdef TYPEINFO_DEBUG_TEST
-#include "typeinfo.h"
+#include "vm/jit/verify/typeinfo.h"
 #endif
 
+#ifdef TYPECHECK_STATISTICS
+void typecheck_print_statistics(FILE *file);
+#endif
 
-bool cacao_initializing;
+/* getmainclassfromjar *********************************************************
 
-char *classpath;                        /* contains classpath                 */
-char *mainstring;
-static classinfo *mainclass;
+   Gets the name of the main class form a JAR's manifest file.
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-void **stackbottom = 0;
-#endif
+*******************************************************************************/
 
-/* define command line options ************************************************/
-
-#define OPT_CLASSPATH   2
-#define OPT_D           3
-#define OPT_MS          4
-#define OPT_MX          5
-#define OPT_VERBOSE1    6
-#define OPT_VERBOSE     7
-#define OPT_VERBOSEGC   8
-#define OPT_VERBOSECALL 9
-#define OPT_NOIEEE      10
-#define OPT_SOFTNULL    11
-#define OPT_TIME        12
-#define OPT_STAT        13
-#define OPT_LOG         14
-#define OPT_CHECK       15
-#define OPT_LOAD        16
-#define OPT_METHOD      17
-#define OPT_SIGNATURE   18
-#define OPT_SHOW        19
-#define OPT_ALL         20
-#define OPT_OLOOP       24
-#define OPT_INLINING   25
-#define OPT_RT          26
-#define OPT_XTA         27 
-#define OPT_VTA         28
-#define OPT_VERBOSETC   29
-#define OPT_NOVERIFY    30
-#define OPT_LIBERALUTF  31
-#define OPT_VERBOSEEXCEPTION 32
-#define OPT_EAGER            33
-#define OPT_LSRA 34
-
-
-opt_struct opts[] = {
-       {"classpath",        true,   OPT_CLASSPATH},
-       {"cp",               true,   OPT_CLASSPATH},
-       {"D",                true,   OPT_D},
-       {"Xms",              true,   OPT_MS},
-       {"Xmx",              true,   OPT_MX},
-       {"ms",               true,   OPT_MS},
-       {"mx",               true,   OPT_MX},
-       {"noasyncgc",        false,  OPT_IGNORE},
-       {"noverify",         false,  OPT_NOVERIFY},
-       {"liberalutf",       false,  OPT_LIBERALUTF},
-       {"oss",              true,   OPT_IGNORE},
-       {"ss",               true,   OPT_IGNORE},
-       {"v",                false,  OPT_VERBOSE1},
-       {"verbose",          false,  OPT_VERBOSE},
-       {"verbosegc",        false,  OPT_VERBOSEGC},
-       {"verbosecall",      false,  OPT_VERBOSECALL},
-       {"verboseexception", false,  OPT_VERBOSEEXCEPTION},
-#ifdef TYPECHECK_VERBOSE
-       {"verbosetc",        false,  OPT_VERBOSETC},
-#endif
-#if defined(__ALPHA__)
-       {"noieee",           false,  OPT_NOIEEE},
-#endif
-       {"softnull",         false,  OPT_SOFTNULL},
-       {"time",             false,  OPT_TIME},
-       {"stat",             false,  OPT_STAT},
-       {"log",              true,   OPT_LOG},
-       {"c",                true,   OPT_CHECK},
-       {"l",                false,  OPT_LOAD},
-    { "eager",            false,  OPT_EAGER },
-       {"m",                true,   OPT_METHOD},
-       {"sig",              true,   OPT_SIGNATURE},
-       {"s",                true,   OPT_SHOW},
-       {"all",              false,  OPT_ALL},
-       {"oloop",            false,  OPT_OLOOP},
-       {"i",                    true,   OPT_INLINING},
-       {"rt",               false,  OPT_RT},
-       {"xta",              false,  OPT_XTA},
-       {"vta",              false,  OPT_VTA},
-       {"lsra", false, OPT_LSRA},
-       {NULL,               false,  0}
-};
-
-
-/******************** interne Function: print_usage ************************
-
-Prints the correct usage syntax to stdout.
-
-***************************************************************************/
-
-static void usage()
+static char *getmainclassnamefromjar(char *mainstring)
 {
-       printf("USAGE: cacao [options] classname [program arguments]\n");
-       printf("Options:\n");
-       printf("          -cp path ............. specify a path to look for classes\n");
-       printf("          -classpath path ...... specify a path to look for classes\n");
-       printf("          -Dpropertyname=value . add an entry to the property list\n");
-       printf("          -Xmx maxmem[kK|mM] ... specify the size for the heap\n");
-       printf("          -Xms initmem[kK|mM] .. specify the initial size for the heap\n");
-       printf("          -mx maxmem[kK|mM] .... specify the size for the heap\n");
-       printf("          -ms initmem[kK|mM] ... specify the initial size for the heap\n");
-       printf("          -v ................... write state-information\n");
-       printf("          -verbose ............. write more information\n");
-       printf("          -verbosegc ........... write message for each GC\n");
-       printf("          -verbosecall ......... write message for each call\n");
-       printf("          -verboseexception .... write message for each step of stack unwinding\n");
-#ifdef TYPECHECK_VERBOSE
-       printf("          -verbosetc ........... write debug messages while typechecking\n");
-#endif
-#if defined(__ALPHA__)
-       printf("          -noieee .............. don't use ieee compliant arithmetic\n");
-#endif
-       printf("          -noverify ............ don't verify classfiles\n");
-       printf("          -liberalutf........... don't warn about overlong UTF-8 sequences\n");
-       printf("          -softnull ............ use software nullpointer check\n");
-       printf("          -time ................ measure the runtime\n");
-       printf("          -stat ................ detailed compiler statistics\n");
-       printf("          -log logfile ......... specify a name for the logfile\n");
-       printf("          -c(heck)b(ounds) ..... don't check array bounds\n");
-       printf("                  s(ync) ....... don't check for synchronization\n");
-       printf("          -oloop ............... optimize array accesses in loops\n"); 
-       printf("          -l ................... don't start the class after loading\n");
-       printf("          -eager ............... perform eager class loading and linking\n");
-       printf("          -all ................. compile all methods, no execution\n");
-       printf("          -m ................... compile only a specific method\n");
-       printf("          -sig ................. specify signature for a specific method\n");
-       printf("          -s(how)a(ssembler) ... show disassembled listing\n");
-       printf("                 c(onstants) ... show the constant pool\n");
-       printf("                 d(atasegment).. show data segment listing\n");
-       printf("                 i(ntermediate). show intermediate representation\n");
-       printf("                 m(ethods)...... show class fields and methods\n");
-       printf("                 u(tf) ......... show the utf - hash\n");
-       printf("          -i     n ............. activate inlining\n");
-       printf("                 v ............. inline virtual methods\n");
-       printf("                                 uses/turns rt option on\n");
-       printf("                 e ............. inline methods with exceptions\n");
-       printf("                 p ............. optimize argument renaming\n");
-       printf("                 o ............. inline methods of foreign classes\n");
-       printf("          -rt .................. use rapid type analysis\n");
-       printf("          -xta ................. use x type analysis\n");
-       printf("          -vta ................. use variable type analysis\n");
-       printf("          -lsra ................ use linear scan register allocation\n");
-
-       /* exit with error code */
-
-       exit(1);
-}   
+       classinfo         *c;
+       java_objectheader *o;
+       methodinfo        *m;
+       java_lang_String  *s;
 
+       c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
 
-#ifdef TYPECHECK_STATISTICS
-void typecheck_print_statistics(FILE *file);
-#endif
+       if (!c)
+               throw_main_exception_exit();
+       
+       /* create JarFile object */
 
+       o = builtin_new(c);
 
-/*
- * void exit_handler(void)
- * -----------------------
- * The exit_handler function is called upon program termination to shutdown
- * the various subsystems and release the resources allocated to the VM.
- */
-void exit_handler(void)
-{
-       /********************* Print debug tables ************************/
-                               
-       if (showmethods) class_showmethods(mainclass);
-       if (showconstantpool) class_showconstantpool(mainclass);
-       if (showutf) utf_show();
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       clear_thread_flags();           /* restores standard file descriptor
-                                      flags */
-#endif
+       if (!o)
+               throw_main_exception_exit();
 
-       /************************ Free all resources *******************/
 
-       loader_close();
-       tables_close();
+       m = class_resolveclassmethod(c,
+                                                                utf_init, 
+                                                                utf_java_lang_String__void,
+                                                                class_java_lang_Object,
+                                                                true);
 
-       MFREE(classpath, u1, strlen(classpath));
+       if (!m)
+               throw_main_exception_exit();
 
-       if (opt_verbose || getcompilingtime || opt_stat) {
-               log_text("CACAO terminated");
-               if (opt_stat) {
-                       print_stats();
-#ifdef TYPECHECK_STATISTICS
-                       typecheck_print_statistics(get_logfile());
-#endif
-               }
-               if (getcompilingtime)
-                       print_times();
-               mem_usagelog(1);
-       }
-}
+       s = javastring_new_from_ascii(mainstring);
 
+       (void) vm_call_method(m, o, s);
 
-/************************** Function: main *******************************
+       if (*exceptionptr)
+               throw_main_exception_exit();
 
-   The main program.
-   
-**************************************************************************/
+       /* get manifest object */
 
-int main(int argc, char **argv)
-{
-       s4 i, j;
-       void *dummy;
-       
-       /********** interne (nur fuer main relevante Optionen) **************/
-   
-       char logfilename[200] = "";
-       u4 heapmaxsize = 64 * 1024 * 1024;
-       u4 heapstartsize = 200 * 1024;
-       char *cp;
-       bool startit = true;
-       char *specificmethodname = NULL;
-       char *specificsignature = NULL;
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       stackbottom = &dummy;
-#endif
-       
-       if (atexit(exit_handler))
-               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                  "Unable to register exit_handler");
+       m = class_resolveclassmethod(c,
+                                                                utf_new_char("getManifest"), 
+                                                                utf_new_char("()Ljava/util/jar/Manifest;"),
+                                                                class_java_lang_Object,
+                                                                true);
+
+       if (!m)
+               throw_main_exception_exit();
+
+       o = vm_call_method(m, o);
+
+       if (o == NULL) {
+               fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
+               vm_exit(1);
+       }
+
+
+       /* get Main Attributes */
 
+       m = class_resolveclassmethod(o->vftbl->class,
+                                                                utf_new_char("getMainAttributes"), 
+                                                                utf_new_char("()Ljava/util/jar/Attributes;"),
+                                                                class_java_lang_Object,
+                                                                true);
 
-       /************ Collect info from the environment ************************/
+       if (!m)
+               throw_main_exception_exit();
 
-       /* set an initial, minimal classpath */
-       classpath = MNEW(char, 2);
-       strcpy(classpath, ".");
+       o = vm_call_method(m, o);
 
-       /* get classpath environment */
-       cp = getenv("CLASSPATH");
-       if (cp) {
-               classpath = MREALLOC(classpath,
-                                                        char,
-                                                        strlen(classpath),
-                                                        strlen(classpath) + 1 + strlen(cp) + 1);
-               strcat(classpath, ":");
-               strcat(classpath, cp);
+       if (o == NULL) {
+               fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
+               vm_exit(1);
        }
 
-       /***************** Interpret the command line *****************/
-   
-       checknull = false;
-       opt_noieee = false;
 
-       while ((i = get_opt(argc, argv, opts)) != OPT_DONE) {
-               switch (i) {
-               case OPT_IGNORE:
-                       break;
-                       
-               case OPT_CLASSPATH:
-                       /* forget old classpath and set the argument as new classpath */
-                       MFREE(classpath, char, strlen(classpath));
-
-                       classpath = MNEW(char, strlen(opt_arg) + 1);
-                       strcpy(classpath, opt_arg);
-                       break;
-                               
-               case OPT_D:
-                       {
-                               int n;
-                               int l = strlen(opt_arg);
-                               for (n = 0; n < l; n++) {
-                                       if (opt_arg[n] == '=') {
-                                               opt_arg[n] = '\0';
-                                               create_property(opt_arg, opt_arg + n + 1);
-                                               goto didit;
-                                       }
-                               }
-                               usage();
-                                       
-                       didit: ;
-                       }       
-                       break;
+       /* get property Main-Class */
 
-               case OPT_MS:
-               case OPT_MX:
-                       {
-                               char c;
-                               c = opt_arg[strlen(opt_arg) - 1];
+       m = class_resolveclassmethod(o->vftbl->class,
+                                                                utf_new_char("getValue"), 
+                                                                utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
+                                                                class_java_lang_Object,
+                                                                true);
 
-                               if (c == 'k' || c == 'K') {
-                                       j = 1024 * atoi(opt_arg);
+       if (!m)
+               throw_main_exception_exit();
 
-                               } else if (c == 'm' || c == 'M') {
-                                       j = 1024 * 1024 * atoi(opt_arg);
+       s = javastring_new_from_ascii("Main-Class");
 
-                               } else j = atoi(opt_arg);
+       o = vm_call_method(m, o, s);
 
-                               if (i == OPT_MX) heapmaxsize = j;
-                               else heapstartsize = j;
-                       }
-                       break;
-
-               case OPT_VERBOSE1:
-                       opt_verbose = true;
-                       break;
-
-               case OPT_VERBOSE:
-                       opt_verbose = true;
-                       loadverbose = true;
-                       linkverbose = true;
-                       initverbose = true;
-                       compileverbose = true;
-                       break;
-
-               case OPT_VERBOSEEXCEPTION:
-                       verboseexception = true;
-                       break;
-
-               case OPT_VERBOSEGC:
-                       collectverbose = true;
-                       break;
-
-#ifdef TYPECHECK_VERBOSE
-               case OPT_VERBOSETC:
-                       typecheckverbose = true;
-                       break;
-#endif
-                               
-               case OPT_VERBOSECALL:
-                       runverbose = true;
-                       break;
-                               
-               case OPT_NOIEEE:
-                       opt_noieee = true;
-                       break;
-
-               case OPT_NOVERIFY:
-                       opt_verify = false;
-                       break;
-
-               case OPT_LIBERALUTF:
-                       opt_liberalutf = true;
-                       break;
-
-               case OPT_SOFTNULL:
-                       checknull = true;
-                       break;
-
-               case OPT_TIME:
-                       getcompilingtime = true;
-                       getloadingtime = true;
-                       break;
-                                       
-               case OPT_STAT:
-                       opt_stat = true;
-                       break;
-                                       
-               case OPT_LOG:
-                       strcpy(logfilename, opt_arg);
-                       break;
-                       
-               case OPT_CHECK:
-                       for (j = 0; j < strlen(opt_arg); j++) {
-                               switch (opt_arg[j]) {
-                               case 'b':
-                                       checkbounds = false;
-                                       break;
-                               case 's':
-                                       checksync = false;
-                                       break;
-                               default:
-                                       usage();
-                               }
-                       }
-                       break;
-                       
-               case OPT_LOAD:
-                       startit = false;
-                       makeinitializations = false;
-                       break;
-
-               case OPT_EAGER:
-                       opt_eager = true;
-                       break;
-
-               case OPT_METHOD:
-                       startit = false;
-                       specificmethodname = opt_arg;
-                       makeinitializations = false;
-                       break;
-                       
-               case OPT_SIGNATURE:
-                       specificsignature = opt_arg;
-                       break;
-                       
-               case OPT_ALL:
-                       compileall = true;
-                       startit = false;
-                       makeinitializations = false;
-                       break;
-                       
-               case OPT_SHOW:       /* Display options */
-                       for (j = 0; j < strlen(opt_arg); j++) {         
-                               switch (opt_arg[j]) {
-                               case 'a':
-                                       showdisassemble = true;
-                                       compileverbose = true;
-                                       break;
-                               case 'c':
-                                       showconstantpool = true;
-                                       break;
-                               case 'd':
-                                       showddatasegment = true;
-                                       break;
-                               case 'i':
-                                       showintermediate = true;
-                                       compileverbose = true;
-                                       break;
-                               case 'm':
-                                       showmethods = true;
-                                       break;
-                               case 'u':
-                                       showutf = true;
-                                       break;
-                               default:
-                                       usage();
-                               }
-                       }
-                       break;
-                       
-               case OPT_OLOOP:
-                       opt_loops = true;
-                       break;
-
-               case OPT_INLINING:
-                       for (j = 0; j < strlen(opt_arg); j++) {         
-                               switch (opt_arg[j]) {
-                               case 'n':
-                                    /* define in options.h; Used in main.c, jit.c & inline.c */
-                                    #ifdef INAFTERMAIN
-                                       useinliningm = true;
-                                       useinlining = false;
-                                    #else
-                                       useinlining = true;
-                                    #endif
-                                       break;
-                               case 'v':
-                                       inlinevirtuals = true;
-                                       opt_rt = true;
-                                       break;
-                               case 'e':
-                                       inlineexceptions = true;
-                                       break;
-                               case 'p':
-                                       inlineparamopt = true;
-                                       break;
-                               case 'o':
-                                       inlineoutsiders = true;
-                                       break;
-                               default:
-                                       usage();
-                               }
-                       }
-                       break;
-
-               case OPT_RT:
-                       opt_rt = true;
-                       break;
-
-               case OPT_XTA:
-                       opt_xta = false; /**not yet **/
-                       break;
-
-               case OPT_VTA:
-                       /***opt_vta = true; not yet **/
-                       break;
-
-               case OPT_LSRA:
-#if defined(__I386__) || defined(__ALPHA__)
-                       opt_lsra = true;
-#else
-                       printf("LSRA not available for this architecture\n");
-                       opt_lsra = false;
-#endif
-                       break;
+       if (!o)
+               throw_main_exception_exit();
 
-               default:
-                       usage();
-               }
-       }
+       return javastring_tochar(o);
+}
 
-       if (opt_ind >= argc)
-               usage();
+void exit_handler(void);
 
-#if 0
-       {
-               char *gnucp = "/home/twisti/src/cacao/cacaodev/classpath/lib/:";
-               cp = classpath;
 
-               classpath = MNEW(char, strlen(cp) + strlen(classpath) + 1);
-               strcpy(classpath, gnucp);
-               strcat(classpath, cp);
 
-               MFREE(cp, char, strlen(cp));
-       }
-#endif
+/* main ************************************************************************
 
-       mainstring = argv[opt_ind++];
-       for (i = strlen(mainstring) - 1; i >= 0; i--) {     /* Transform dots into slashes */
-               if (mainstring[i] == '.') mainstring[i] = '/';  /* in the class name */
-       }
+   The main program.
+   
+*******************************************************************************/
+
+int main(int argc, char **argv)
+{
+       s4 i;
+       
+       /* local variables ********************************************************/
+
+       JavaVMInitArgs *vm_args;
+       JavaVM         *jvm;                /* denotes a Java VM                  */
+
+       if (atexit(vm_exit_handler))
+               throw_cacao_exception_exit(string_java_lang_InternalError,
+                                                                  "Unable to register exit_handler");
 
 
        /**************************** Program start *****************************/
 
-       log_init(logfilename);
        if (opt_verbose)
                log_text("CACAO started -------------------------------------------------------");
 
-       /* initialize the garbage collector */
-       gc_init(heapmaxsize, heapstartsize);
+       /* prepare the options */
 
-       tables_init();
-       suck_init(classpath);
+       vm_args = options_prepare(argc, argv);
+       
+       /* load and initialize a Java VM, return a JNI interface pointer in env */
 
-       cacao_initializing = true;
+       JNI_CreateJavaVM(&jvm, (void *) &_Jv_env, vm_args);
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-       initThreadsEarly();
-#endif
-       initLocks();
+#if defined(ENABLE_JVMTI)
+       pthread_mutex_init(&dbgcomlock,NULL);
+       if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
 #endif
 
-       /* install architecture dependent signal handler used for exceptions */
-       init_exceptions();
-
-       /* initializes jit compiler and codegen stuff */
-       jit_init();
+       /* do we have a main class? */
 
-       loader_init((u1 *) &dummy);
+       if (mainstring == NULL)
+               usage();
 
-       /* initialize exceptions used in the system */
-       if (!init_system_exceptions())
-               throw_main_exception_exit();
 
-       native_loadclasses();
+       /* start worker routines **************************************************/
 
-#if defined(USE_THREADS)
-       initThreads((u1 *) &dummy);
-#endif
+       if (opt_run == true) {
+               utf              *mainutf;
+               classinfo        *mainclass;
+               methodinfo       *m;
+               java_objectarray *oa; 
+               s4                oalength;
+               java_lang_String *s;
+               s4                status;
 
-       *threadrootmethod = NULL;
+               /* set return value to OK */
 
-       /*That's important, otherwise we get into trouble, if the Runtime static
-         initializer is called before (circular dependency. This is with
-         classpath 0.09. Another important thing is, that this has to happen
-         after initThreads!!! */
+               status = 0;
 
-       if (!class_init(class_new(utf_new_char("java/lang/System"))))
-               throw_main_exception_exit();
+               if (opt_jar == true) {
+                       /* open jar file with java.util.jar.JarFile */
+                       mainstring = getmainclassnamefromjar(mainstring);
+               }
 
-       
-       
-/*        jni_init(); */
-       cacao_initializing = false;
+               /* load the main class */
 
-       /************************* Start worker routines ********************/
+               mainutf = utf_new_char(mainstring);
 
-       if (startit) {
-               methodinfo *mainmethod;
-               java_objectarray *a; 
-               s4 status;
+               if (!(mainclass = load_class_from_sysloader(mainutf)))
+                       throw_main_exception_exit();
 
-               /* set return value to OK */
-               status = 0;
+               /* error loading class, clear exceptionptr for new exception */
 
-               /* create, load and link the main class */
-               mainclass = class_new(utf_new_char(mainstring));
+               if (*exceptionptr || !mainclass) {
+/*                     *exceptionptr = NULL; */
 
-               if (!class_load(mainclass))
+/*                     *exceptionptr = */
+/*                             new_exception_message(string_java_lang_NoClassDefFoundError, */
+/*                                                                       mainstring); */
                        throw_main_exception_exit();
+               }
 
-               if (!class_link(mainclass))
+               if (!link_class(mainclass))
                        throw_main_exception_exit();
+                       
+               /* find the `main' method of the main class */
 
-               mainmethod = class_resolveclassmethod(mainclass,
-                                                                                         utf_new_char("main"), 
-                                                                                         utf_new_char("([Ljava/lang/String;)V"),
-                                                                                         mainclass,
-                                                                                         false);
+               m = class_resolveclassmethod(mainclass,
+                                                                        utf_new_char("main"), 
+                                                                        utf_new_char("([Ljava/lang/String;)V"),
+                                                                        class_java_lang_Object,
+                                                                        false);
 
-               /* problems with main method? */
-/*             if (*exceptionptr) */
-/*                     throw_exception_exit(); */
+               if (*exceptionptr) {
+                       throw_main_exception_exit();
+               }
 
                /* there is no main method or it isn't static */
-               if (!mainmethod || !(mainmethod->flags & ACC_STATIC)) {
+
+               if (!m || !(m->flags & ACC_STATIC)) {
+                       *exceptionptr = NULL;
+
                        *exceptionptr =
                                new_exception_message(string_java_lang_NoSuchMethodError,
                                                                          "main");
                        throw_main_exception_exit();
                }
 
-               a = builtin_anewarray(argc - opt_ind, class_java_lang_String);
-               for (i = opt_ind; i < argc; i++) {
-                       a->data[i - opt_ind] = 
-                               (java_objectheader *) javastring_new(utf_new_char(argv[i]));
+               /* build argument array */
+
+               oalength = vm_args->nOptions - opt_index;
+
+               oa = builtin_anewarray(oalength, class_java_lang_String);
+
+               for (i = 0; i < oalength; i++) {
+                       s = javastring_new(utf_new_char(vm_args->options[opt_index + i].optionString));
+                       oa->data[i] = (java_objectheader *) s;
                }
 
 #ifdef TYPEINFO_DEBUG_TEST
@@ -679,93 +307,125 @@ int main(int argc, char **argv)
 #endif
                /*class_showmethods(currentThread->group->header.vftbl->class); */
 
-               *threadrootmethod = mainmethod;
-
+#if defined(ENABLE_JVMTI)
+               jvmti_set_phase(JVMTI_PHASE_LIVE);
+#endif
 
-               /* here we go... */
-               asm_calljavafunction(mainmethod, a, NULL, NULL, NULL);
+               (void) vm_call_method(m, NULL, oa);
 
                /* exception occurred? */
+
                if (*exceptionptr) {
                        throw_main_exception();
                        status = 1;
                }
 
-#if defined(USE_THREADS)
-#if defined(NATIVE_THREADS)
-               joinAllThreads();
-#else
-               killThread(currentThread);
-#endif
-#endif
+               /* unload the JavaVM */
 
-               /* now exit the JavaVM */
+               vm_destroy(jvm);
 
-               cacao_exit(status);
+               /* and exit */
+
+               vm_exit(status);
        }
 
-       /************* If requested, compile all methods ********************/
 
+       /* If requested, compile all methods. *************************************/
+
+#if !defined(NDEBUG)
        if (compileall) {
                classinfo *c;
                methodinfo *m;
                u4 slot;
                s4 i;
+               classcache_name_entry *nmen;
+               classcache_class_entry *clsen;
 
-               /* create all classes found in the classpath */
+               /* create all classes found in the bootclasspath */
                /* XXX currently only works with zip/jar's */
-               create_all_classes();
-
-               /* load and link all classes */
-               for (slot = 0; slot < class_hash.size; slot++) {
-                       c = class_hash.ptr[slot];
-
-                       while (c) {
-                               if (!c->loaded)
-                                       if (!class_load(c))
-                                               throw_main_exception_exit();
-
-                               if (!c->linked)
-                                       if (!class_link(c))
-                                               throw_main_exception_exit();
-
-                               /* compile all class methods */
-                               for (i = 0; i < c->methodscount; i++) {
-                                       m = &(c->methods[i]);
-                                       if (m->jcode) {
-                                               (void) jit_compile(m);
+
+               loader_load_all_classes();
+
+               /* link all classes */
+
+               for (slot = 0; slot < hashtable_classcache.size; slot++) {
+                       nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+                       for (; nmen; nmen = nmen->hashlink) {
+                               /* iterate over all class entries */
+
+                               for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                                       c = clsen->classobj;
+
+                                       if (!c)
+                                               continue;
+
+                                       if (!(c->state & CLASS_LINKED)) {
+                                               if (!link_class(c)) {
+                                                       fprintf(stderr, "Error linking: ");
+                                                       utf_fprint_printable_ascii_classname(stderr, c->name);
+                                                       fprintf(stderr, "\n");
+
+                                                       /* print out exception and cause */
+
+                                                       exceptions_print_exception(*exceptionptr);
+
+                                                       /* goto next class */
+
+                                                       continue;
+                                               }
                                        }
-                               }
 
-                               c = c->hashlink;
+                                       /* compile all class methods */
+
+                                       for (i = 0; i < c->methodscount; i++) {
+                                               m = &(c->methods[i]);
+
+                                               if (m->jcode) {
+                                                       if (!jit_compile(m)) {
+                                                               fprintf(stderr, "Error compiling: ");
+                                                               utf_fprint_printable_ascii_classname(stderr, c->name);
+                                                               fprintf(stderr, ".");
+                                                               utf_fprint_printable_ascii(stderr, m->name);
+                                                               utf_fprint_printable_ascii(stderr, m->descriptor);
+                                                               fprintf(stderr, "\n");
+
+                                                               /* print out exception and cause */
+
+                                                               exceptions_print_exception(*exceptionptr);
+                                                       }
+                                               }
+                                       }
+                               }
                        }
                }
        }
+#endif /* !defined(NDEBUG) */
 
 
-       /******** If requested, compile a specific method ***************/
+       /* If requested, compile a specific method. *******************************/
 
-       if (specificmethodname) {
+#if !defined(NDEBUG)
+       if (opt_method != NULL) {
                methodinfo *m;
 
                /* create, load and link the main class */
-               mainclass = class_new(utf_new_char(mainstring));
 
-               if (!class_load(mainclass))
+               if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
                        throw_main_exception_exit();
 
-               if (!class_link(mainclass))
+               if (!link_class(mainclass))
                        throw_main_exception_exit();
 
-               if (specificsignature) {
+               if (opt_signature != NULL) {
                        m = class_resolveclassmethod(mainclass,
-                                                                                utf_new_char(specificmethodname),
-                                                                                utf_new_char(specificsignature),
+                                                                                utf_new_char(opt_method),
+                                                                                utf_new_char(opt_signature),
                                                                                 mainclass,
                                                                                 false);
                } else {
                        m = class_resolveclassmethod(mainclass,
-                                                                                utf_new_char(specificmethodname),
+                                                                                utf_new_char(opt_method),
                                                                                 NULL,
                                                                                 mainclass,
                                                                                 false);
@@ -773,8 +433,8 @@ int main(int argc, char **argv)
 
                if (!m) {
                        char message[MAXLOGTEXT];
-                       sprintf(message, "%s%s", specificmethodname,
-                                       specificsignature ? specificsignature : "");
+                       sprintf(message, "%s%s", opt_method,
+                                       opt_signature ? opt_signature : "");
 
                        *exceptionptr =
                                new_exception_message(string_java_lang_NoSuchMethodException,
@@ -786,7 +446,8 @@ int main(int argc, char **argv)
                jit_compile(m);
        }
 
-       cacao_shutdown(0);
+       vm_shutdown(0);
+#endif /* !defined(NDEBUG) */
 
        /* keep compiler happy */
 
@@ -794,78 +455,6 @@ int main(int argc, char **argv)
 }
 
 
-/* cacao_exit ******************************************************************
-
-   Calls java.lang.Runtime.exit(I)V to exit the JavaVM correctly.
-
-*******************************************************************************/
-
-void cacao_exit(s4 status)
-{
-       classinfo *c;
-       methodinfo *m;
-
-       /* class should already be loaded, but who knows... */
-
-       c = class_new(utf_new_char("java/lang/System"));
-
-       if (!class_load(c))
-               throw_main_exception_exit();
-
-       if (!class_link(c))
-               throw_main_exception_exit();
-
-       /* call System.exit(I)V */
-
-       m = class_resolveclassmethod(c,
-                                                                utf_new_char("exit"),
-                                                                utf_new_char("(I)V"),
-                                                                class_java_lang_Object,
-                                                                true);
-       
-       if (!m)
-               throw_main_exception_exit();
-
-       /* call the exit function with passed exit status */
-
-       asm_calljavafunction(m,
-#if POINTERSIZE == 8
-                                                (void *) (s8) status,
-#else
-                                                (void *) status,
-#endif
-                                                NULL,
-                                                NULL,
-                                                NULL);
-
-       /* this should never happen */
-
-       if (*exceptionptr)
-               throw_exception_exit();
-
-       throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                          "System.exit(I)V returned without exception");
-}
-
-
-/*************************** Shutdown function *********************************
-
-       Terminates the system immediately without freeing memory explicitly (to be
-       used only for abnormal termination)
-       
-*******************************************************************************/
-
-void cacao_shutdown(s4 status)
-{
-       if (opt_verbose || getcompilingtime || opt_stat) {
-               log_text("CACAO terminated by shutdown");
-               dolog("Exit status: %d\n", (s4) status);
-       }
-
-       exit(status);
-}
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where