Calling convention fixes.
[cacao.git] / src / vm / loader.c
index e1f066ab2e880892fd4ea159732452a5732cfa95..2a4681af59d61a9e554dc78ed3b8a0762f6fb612 100644 (file)
@@ -1,9 +1,9 @@
-/* loader.c - class loader functions
+/* vm/loader.c - class loader functions
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   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 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,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
@@ -32,7 +32,7 @@
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 1544 2004-11-18 12:21:44Z twisti $
+   $Id: loader.c 1936 2005-02-10 11:04:10Z twisti $
 
 */
 
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
-#include "exceptions.h"
-#include "global.h"
-#include "loader.h"
-#include "options.h"
-#include "native.h"
-#include "tables.h"
-#include "builtin.h"
-#include "jit/jit.h"
-#include "asmpart.h"
-#include "statistics.h"
-#include "toolbox/memory.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_Throwable.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+#  include "threads/native/threads.h"
+# else
+#  include "threads/green/threads.h"
+#  include "threads/green/locks.h"
+# endif
+#endif
+
 #include "toolbox/logging.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
-#include "nat/java_lang_Throwable.h"
+#include "vm/exceptions.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
 
-#ifdef USE_ZLIB
-#include "unzip.h"
+#if defined(USE_ZLIB)
+# include "vm/unzip.h"
 #endif
 
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+
+
 #undef JOWENN_DEBUG
 #undef JOWENN_DEBUG1
 #undef JOWENN_DEBUG2
@@ -71,52 +83,8 @@ static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
 
-/* utf-symbols for pointer comparison of frequently used strings */
-
-static utf *utf_innerclasses;          /* InnerClasses                           */
-static utf *utf_constantvalue;                 /* ConstantValue                          */
-static utf *utf_code;                      /* Code                                   */
-static utf *utf_exceptions;         /* Exceptions                             */
-static utf *utf_linenumbertable;    /* LineNumberTable                        */
-static utf *utf_sourcefile;         /* SourceFile                             */
-static utf *utf_finalize;                  /* finalize                               */
-static utf *utf_fidesc;                    /* ()V changed                            */
-static utf *utf_init;                          /* <init>                                 */
-static utf *utf_clinit;                    /* <clinit>                               */
-static utf *utf_initsystemclass;       /* initializeSystemClass                  */
-static utf *utf_systemclass;           /* java/lang/System                       */
-static utf *utf_vmclassloader;      /* java/lang/VMClassLoader                */
-static utf *utf_vmclass;            /* java/lang/VMClassLoader                */
-static utf *utf_initialize;
-static utf *utf_initializedesc;
-static utf *utf_java_lang_Object;   /* java/lang/Object                       */
-
-utf *utf_fillInStackTrace_name;
-utf *utf_fillInStackTrace_desc;
-
-utf* clinit_desc(){
-       return utf_fidesc;
-}
-utf* clinit_name(){
-       return utf_clinit;
-}
-
-
-/* important system classes ***************************************************/
-
-classinfo *class_java_lang_Object;
-classinfo *class_java_lang_String;
-classinfo *class_java_lang_Cloneable;
-classinfo *class_java_io_Serializable;
-
-/* Pseudo classes for the typechecker */
-classinfo *pseudo_class_Arraystub = NULL;
-classinfo *pseudo_class_Null = NULL;
-classinfo *pseudo_class_New = NULL;
 vftbl_t *pseudo_class_Arraystub_vftbl = NULL;
 
-utf *array_packagename = NULL;
-
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
@@ -323,8 +291,12 @@ void suck_init(char *classpath)
        classpath_info *cpi;
        classpath_info *lastcpi;
 
-       if (!classpath)
-               return;
+       /* search for last classpath entry (only if there already some) */
+
+       if ((lastcpi = classpath_entries)) {
+               while (lastcpi->next)
+                       lastcpi = lastcpi->next;
+       }
 
        for (start = classpath; (*start) != '\0';) {
 
@@ -344,7 +316,7 @@ void suck_init(char *classpath)
 
                        /* allocate memory for filename and fill it */
 
-                       filename = MNEW(char, filenamelen + 1);
+                       filename = MNEW(char, filenamelen + 2);  /* 2 = "/\0" */
                        strncpy(filename, start, filenamelen);
                        filename[filenamelen + 1] = '\0';
                        cpi = NULL;
@@ -354,45 +326,42 @@ void suck_init(char *classpath)
                                unzFile uf = unzOpen(filename);
 
                                if (uf) {
-                                       cpi = (union classpath_info *) NEW(classpath_info);
-                                       cpi->archive.type = CLASSPATH_ARCHIVE;
-                                       cpi->archive.uf = uf;
-                                       cpi->archive.next = NULL;
+                                       cpi = NEW(classpath_info);
+                                       cpi->type = CLASSPATH_ARCHIVE;
+                                       cpi->uf = uf;
+                                       cpi->next = NULL;
+                                       cpi->pd = NULL; /* ProtectionDomain not set yet */
+                                       cpi->path = filename;
                                }
+
 #else
                                throw_cacao_exception_exit(string_java_lang_InternalError,
                                                                                   "zip/jar files not supported");
 #endif
                                
                        } else {
-                               cpi = (union classpath_info *) NEW(classpath_info);
-                               cpi->filepath.type = CLASSPATH_PATH;
-                               cpi->filepath.next = NULL;
+                               cpi = NEW(classpath_info);
+                               cpi->type = CLASSPATH_PATH;
+                               cpi->next = NULL;
+                               cpi->pd = NULL; /* ProtectionDomain not set yet */
 
-#if 0
                                if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
                                        filename[filenamelen] = '/';
                                        filename[filenamelen + 1] = '\0';
                                        filenamelen++;
                                }
-#endif
-                               cpi->filepath.path = filename;
-                               cpi->filepath.pathlen = filenamelen;
-                       }
-
-                       /* free allocated memory */
 
-                       MFREE(filename, char, filenamelen);
+                               cpi->path = filename;
+                               cpi->pathlen = filenamelen;
+                       }
 
                        /* attach current classpath entry */
 
                        if (cpi) {
-                               if (!classpath_entries) {
+                               if (!classpath_entries)
                                        classpath_entries = cpi;
-
-                               } else {
-                                       lastcpi->filepath.next = cpi;
-                               }
+                               else
+                                       lastcpi->next = cpi;
 
                                lastcpi = cpi;
                        }
@@ -414,13 +383,13 @@ void create_all_classes()
 {
        classpath_info *cpi;
 
-       for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
+       for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
 #if defined(USE_ZLIB)
-               if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
+               if (cpi->type == CLASSPATH_ARCHIVE) {
                        cacao_entry_s *ce;
                        unz_s *s;
 
-                       s = (unz_s *) cpi->archive.uf;
+                       s = (unz_s *) cpi->uf;
                        ce = s->cacao_dir_list;
                                
                        while (ce) {
@@ -455,33 +424,14 @@ classbuffer *suck_start(classinfo *c)
        s4    filenamelen;
        char *path;
        FILE *classfile;
-       int  err;
+       bool found;
        s4 len;
        struct stat buffer;
        classbuffer *cb;
 
-#if 0
-       utf_ptr = c->name->text;
-
-       while (utf_ptr < utf_end(c->name)) {
-               if (filenamelen >= CLASSPATH_MAXFILENAME) {
-                       *exceptionptr =
-                               new_exception_message(string_java_lang_InternalError,
-                                                                         "Filename too long");
-
-                       /* XXX should we exit in such a case? */
-                       throw_exception_exit();
-               }
-
-               ch = *utf_ptr++;
-               if ((ch <= ' ' || ch > 'z') && (ch != '/'))     /* invalid character */
-                       ch = '?';
-               filename[filenamelen++] = ch;
-       }
-#endif
-
        /* initialize return value */
 
+       found = false;
        cb = NULL;
 
        filenamelen = utf_strlen(c->name) + 7;  /* 7 = ".class\0" */
@@ -492,27 +442,39 @@ classbuffer *suck_start(classinfo *c)
 
        /* walk through all classpath entries */
 
-       for (cpi = classpath_entries; !cb && cpi; cpi = cpi->filepath.next) {
+       for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
 #if defined(USE_ZLIB)
-               if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
-                       if (cacao_locate(cpi->archive.uf, c->name) == UNZ_OK) {
+               if (cpi->type == CLASSPATH_ARCHIVE) {
+
+#if defined(USE_THREADS)
+                       /* enter a monitor on zip/jar archives */
+
+                       builtin_monitorenter((java_objectheader *) cpi);
+#endif
+
+                       if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
                                unz_file_info file_info;
 
-                               if (unzGetCurrentFileInfo(cpi->archive.uf, &file_info, filename,
+                               if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
                                                                                  sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
-                                       if (unzOpenCurrentFile(cpi->archive.uf) == UNZ_OK) {
+                                       if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
                                                cb = NEW(classbuffer);
                                                cb->class = c;
                                                cb->size = file_info.uncompressed_size;
                                                cb->data = MNEW(u1, cb->size);
                                                cb->pos = cb->data - 1;
+                                               /* We need this later in use_class_as_object to set a */
+                                               /* correct ProtectionDomain and CodeSource.           */
+                                               c->pd = (struct java_security_ProtectionDomain *) cpi; 
 
-                                               len = unzReadCurrentFile(cpi->archive.uf, cb->data, cb->size);
+                                               len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
 
                                                if (len != cb->size) {
-                                                       MFREE(cb->data, u1, cb->size);
-                                                       FREE(cb, classbuffer);
+                                                       suck_stop(cb);
                                                        log_text("Error while unzipping");
+
+                                               } else {
+                                                       found = true;
                                                }
 
                                        } else {
@@ -523,46 +485,56 @@ classbuffer *suck_start(classinfo *c)
                                        log_text("Error while retrieving fileinfo");
                                }
                        }
-                       unzCloseCurrentFile(cpi->archive.uf);
+                       unzCloseCurrentFile(cpi->uf);
+
+#if defined(USE_THREADS)
+                       /* leave the monitor */
+
+                       builtin_monitorexit((java_objectheader *) cpi);
+#endif
 
                } else {
 #endif /* USE_ZLIB */
                        
-                       path = MNEW(char, cpi->filepath.pathlen + filenamelen + 1);
-                       strcpy(path, cpi->filepath.path);
+                       path = MNEW(char, cpi->pathlen + filenamelen + 1);
+                       strcpy(path, cpi->path);
                        strcat(path, filename);
 
                        classfile = fopen(path, "r");
 
                        if (classfile) {                                   /* file exists */
-                               /* determine size of classfile */
-                               err = stat(path, &buffer);
-
-                               if (!err) {                            /* read classfile data */
+                               if (!stat(path, &buffer)) {            /* read classfile data */
                                        cb = NEW(classbuffer);
                                        cb->class = c;
                                        cb->size = buffer.st_size;
                                        cb->data = MNEW(u1, cb->size);
                                        cb->pos = cb->data - 1;
+                                       /* We need this later in use_class_as_object to set a     */
+                                       /* correct ProtectionDomain and CodeSource.               */
+                                       c->pd = (struct java_security_ProtectionDomain *) cpi; 
 
                                        /* read class data */
                                        len = fread(cb->data, 1, cb->size, classfile);
 
-/*                                     if (len != buffer.st_size) { */
+                                       if (len != buffer.st_size) {
+                                               suck_stop(cb);
 /*                                             if (ferror(classfile)) { */
 /*                                             } */
-/*                                     } */
+
+                                       } else {
+                                               found = true;
+                                       }
                                }
                        }
 
-                       MFREE(path, char, cpi->filepath.pathlen + filenamelen + 1);
+                       MFREE(path, char, cpi->pathlen + filenamelen + 1);
 #if defined(USE_ZLIB)
                }
 #endif
        }
 
        if (opt_verbose) {
-               if (err) 
+               if (!found)
                        dolog("Warning: Can not open class file '%s'", filename);
        }
 
@@ -764,7 +736,7 @@ static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                        return false;
 
-               if (aname == utf_innerclasses) {
+               if (aname == utf_InnerClasses) {
                        /* innerclasses attribute */
                        if (c->innerclass) {
                                *exceptionptr =
@@ -805,7 +777,7 @@ static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
                                info->flags = suck_u2(cb);
                        }
 
-               } else if (aname == utf_sourcefile) {
+               } else if (aname == utf_SourceFile) {
                        if (!check_classbuffer_size(cb, 4 + 2))
                                return false;
 
@@ -1118,7 +1090,7 @@ static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
                if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                        return false;
 
-               if (u == utf_constantvalue) {
+               if (u == utf_ConstantValue) {
                        if (!check_classbuffer_size(cb, 4 + 2))
                                return false;
 
@@ -1391,7 +1363,7 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                        return false;
 
-               if (aname == utf_code) {
+               if (aname == utf_Code) {
                        if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
                                        *exceptionptr =
                                                new_classformaterror(c,
@@ -1494,7 +1466,7 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
                                if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                                        return false;
 
-                               if (caname == utf_linenumbertable) {
+                               if (caname == utf_LineNumberTable) {
                                        u2 lncid;
 
                                        if (!check_classbuffer_size(cb, 4 + 2))
@@ -1526,7 +1498,7 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
                                }
                        }
 
-               } else if (aname == utf_exceptions) {
+               } else if (aname == utf_Exceptions) {
                        s4 j;
 
                        if (m->thrownexceptions) {
@@ -1565,8 +1537,6 @@ static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
        }
 
        /* everything was ok */
-       /*              utf_display(m->name);
-                       printf("\nexceptiontablelength:%ld\n",m->exceptiontablelength);*/
 
        return true;
 }
@@ -1613,6 +1583,24 @@ void method_display(methodinfo *m)
        printf("\n");
 }
 
+/************** Function: method_display_w_class  (debugging only) **************/
+
+void method_display_w_class(methodinfo *m)
+{
+        printflags(m->class->flags);
+        printf(" "); fflush(stdout);
+        utf_display(m->class->name);
+        printf(".");fflush(stdout);
+
+        printf("   ");
+        printflags(m->flags);
+        printf(" "); fflush(stdout);
+        utf_display(m->name);
+        printf(" "); fflush(stdout);
+        utf_display(m->descriptor);
+        printf("\n"); fflush(stdout);
+}
+
 /************** Function: method_display_flags_last  (debugging only) **************/
 
 void method_display_flags_last(methodinfo *m)
@@ -2015,11 +2003,20 @@ static bool class_loadcpool(classbuffer *cb, classinfo *c)
 
                if (opt_verify) {
                        /* check name */
-                       if (!is_valid_name_utf(cn->name))
-                               panic("NameAndType with invalid name");
+                       if (!is_valid_name_utf(cn->name)) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
+
                        /* disallow referencing <clinit> among others */
-                       if (cn->name->text[0] == '<' && cn->name != utf_init)
-                               panic("NameAndType with invalid special name");
+                       if (cn->name->text[0] == '<' && cn->name != utf_init) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
                }
 
                cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
@@ -2094,13 +2091,17 @@ classinfo *class_load(classinfo *c)
        classbuffer *cb;
        classinfo *r;
 
+#if defined(USE_THREADS)
        /* enter a monitor on the class */
 
        builtin_monitorenter((java_objectheader *) c);
+#endif
 
        /* maybe the class is already loaded */
        if (c->loaded) {
+#if defined(USE_THREADS)
                builtin_monitorexit((java_objectheader *) c);
+#endif
 
                return c;
        }
@@ -2125,7 +2126,9 @@ classinfo *class_load(classinfo *c)
                        new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
                                                                         c->name);
 
+#if defined(USE_THREADS)
                builtin_monitorexit((java_objectheader *) c);
+#endif
 
                return NULL;
        }
@@ -2152,9 +2155,11 @@ classinfo *class_load(classinfo *c)
        if (getcompilingtime)
                compilingtime_start();
 
+#if defined(USE_THREADS)
        /* leave the monitor */
 
        builtin_monitorexit((java_objectheader *) c);
+#endif
 
        return r;
 }
@@ -2809,13 +2814,17 @@ classinfo *class_link(classinfo *c)
 {
        classinfo *r;
 
+#if defined(USE_THREADS)
        /* enter a monitor on the class */
 
        builtin_monitorenter((java_objectheader *) c);
+#endif
 
        /* maybe the class is already linked */
        if (c->linked) {
+#if defined(USE_THREADS)
                builtin_monitorexit((java_objectheader *) c);
+#endif
 
                return c;
        }
@@ -2843,9 +2852,11 @@ classinfo *class_link(classinfo *c)
        if (getcompilingtime)
                compilingtime_start();
 
+#if defined(USE_THREADS)
        /* leave the monitor */
 
        builtin_monitorexit((java_objectheader *) c);
+#endif
 
        return r;
 }
@@ -2893,7 +2904,7 @@ static classinfo *class_link_intern(classinfo *c)
                }
 
                if (!tc->loaded)
-                       if (!class_load(tc))
+                       if (!class_load(tc))
                                return NULL;
 
                if (!(tc->flags & ACC_INTERFACE)) {
@@ -3083,24 +3094,20 @@ static classinfo *class_link_intern(classinfo *c)
        
        /* add interfaces */
        
-       for (tc = c; tc != NULL; tc = tc->super) {
-               for (i = 0; i < tc->interfacescount; i++) {
+       for (tc = c; tc != NULL; tc = tc->super)
+               for (i = 0; i < tc->interfacescount; i++)
                        class_addinterface(c, tc->interfaces[i]);
-               }
-       }
 
        /* add finalizer method (not for java.lang.Object) */
 
        if (super) {
                methodinfo *fi;
 
-               fi = class_findmethod(c, utf_finalize, utf_fidesc);
+               fi = class_findmethod(c, utf_finalize, utf_void__void);
 
-               if (fi) {
-                       if (!(fi->flags & ACC_STATIC)) {
+               if (fi)
+                       if (!(fi->flags & ACC_STATIC))
                                c->finalizer = fi;
-                       }
-               }
        }
 
        /* final tasks */
@@ -3691,15 +3698,24 @@ classinfo *class_init(classinfo *c)
        if (!makeinitializations)
                return c;
 
+#if defined(USE_THREADS)
        /* enter a monitor on the class */
 
        builtin_monitorenter((java_objectheader *) c);
+#endif
 
        /* maybe the class is already initalized or the current thread, which can
           pass the monitor, is currently initalizing this class */
 
+       /* JOWENN: In future we need an additinal flag: initializationfailed,
+               since further access to the class should cause a NoClassDefFound,
+               if the static initializer failed once
+        */
+
        if (c->initialized || c->initializing) {
+#if defined(USE_THREADS)
                builtin_monitorexit((java_objectheader *) c);
+#endif
 
                return c;
        }
@@ -3718,9 +3734,11 @@ classinfo *class_init(classinfo *c)
        /* this initalizing run is done */
        c->initializing = false;
 
+#if defined(USE_THREADS)
        /* leave the monitor */
 
        builtin_monitorexit((java_objectheader *) c);
+#endif
 
        return r;
 }
@@ -3788,7 +3806,7 @@ static classinfo *class_init_intern(classinfo *c)
                }
        }
 
-       m = class_findmethod(c, utf_clinit, utf_fidesc);
+       m = class_findmethod(c, utf_clinit, utf_void__void);
 
        if (!m) {
                if (initverbose) {
@@ -4350,7 +4368,6 @@ static void create_pseudo_classes()
 {
     /* pseudo class for Arraystubs (extends java.lang.Object) */
     
-    pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
        pseudo_class_Arraystub->loaded = true;
     pseudo_class_Arraystub->super = class_java_lang_Object;
     pseudo_class_Arraystub->interfacescount = 2;
@@ -4364,18 +4381,15 @@ static void create_pseudo_classes()
 
     /* pseudo class representing the null type */
     
-       pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
        pseudo_class_Null->loaded = true;
     pseudo_class_Null->super = class_java_lang_Object;
        class_link(pseudo_class_Null);  
 
     /* pseudo class representing new uninitialized objects */
     
-       pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
        pseudo_class_New->loaded = true;
        pseudo_class_New->linked = true;
        pseudo_class_New->super = class_java_lang_Object;
-/*     class_link(pseudo_class_New); */
 }
 
 
@@ -4386,52 +4400,41 @@ static void create_pseudo_classes()
 
 *******************************************************************************/
  
-void loader_init(u1 *stackbottom)
+bool loader_init(u1 *stackbottom)
 {
+       classpath_info *cpi;
+
+       /* reset interface index */
+
        interfaceindex = 0;
        
-       /* create utf-symbols for pointer comparison of frequently used strings */
-       utf_innerclasses    = utf_new_char("InnerClasses");
-       utf_constantvalue   = utf_new_char("ConstantValue");
-       utf_code            = utf_new_char("Code");
-       utf_exceptions      = utf_new_char("Exceptions");
-       utf_linenumbertable = utf_new_char("LineNumberTable");
-       utf_sourcefile      = utf_new_char("SourceFile");
-       utf_finalize        = utf_new_char("finalize");
-       utf_fidesc              = utf_new_char("()V");
-       utf_init                = utf_new_char("<init>");
-       utf_clinit              = utf_new_char("<clinit>");
-       utf_initsystemclass = utf_new_char("initializeSystemClass");
-       utf_systemclass     = utf_new_char("java/lang/System");
-       utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
-       utf_initialize      = utf_new_char("initialize");
-       utf_initializedesc  = utf_new_char("(I)V");
-       utf_vmclass         = utf_new_char("java/lang/VMClass");
-       utf_java_lang_Object= utf_new_char("java/lang/Object");
-       array_packagename   = utf_new_char("<the array package>");
-       utf_fillInStackTrace_name = utf_new_char("fillInStackTrace");
-       utf_fillInStackTrace_desc = utf_new_char("()Ljava/lang/Throwable;");
-
-       /* create some important classes */
-       /* These classes have to be created now because the classinfo
-        * pointers are used in the loading code.
-        */
-       class_java_lang_Object = class_new_intern(utf_java_lang_Object);
-       class_load(class_java_lang_Object);
-       class_link(class_java_lang_Object);
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       /* Initialize the monitor pointer for zip/jar file locking.               */
 
-       class_java_lang_String = class_new(utf_new_char("java/lang/String"));
-       class_load(class_java_lang_String);
-       class_link(class_java_lang_String);
+       for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
+               if (cpi->type == CLASSPATH_ARCHIVE) 
+                       initObjectLock(&cpi->header);
+       }
+#endif
 
-       class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
-       class_load(class_java_lang_Cloneable);
-       class_link(class_java_lang_Cloneable);
+       /* Create some important classes. These classes have to be created now    */
+       /* because the classinfo pointers are used in the loading code.           */
 
-       class_java_io_Serializable =
-               class_new(utf_new_char("java/io/Serializable"));
-       class_load(class_java_io_Serializable);
-       class_link(class_java_io_Serializable);
+       if (!class_load(class_java_lang_Object) ||
+               !class_link(class_java_lang_Object))
+               return false;
+
+       if (!class_load(class_java_lang_String) ||
+               !class_link(class_java_lang_String))
+               return false;
+
+       if (!class_load(class_java_lang_Cloneable) ||
+               !class_link(class_java_lang_Cloneable))
+               return false;
+
+       if (!class_load(class_java_io_Serializable) ||
+               !class_link(class_java_io_Serializable))
+               return false;
 
        /* create classes representing primitive types */
        create_primitive_classes();
@@ -4446,6 +4449,8 @@ void loader_init(u1 *stackbottom)
        if (stackbottom != 0)
                initLocks();
 #endif
+
+       return true;
 }