* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / loader.c
index cf5466d2042693fdcabc317573599cf96ce11a6a..2abe53ed3326c29dc86f058e7008e507b1c5d3d6 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/loader.c - class loader functions
 
-   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
+   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, 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
 
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 2182 2005-04-01 20:56:33Z edwin $
+   $Id: loader.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
 
+#include "config.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include <sys/stat.h>
 
-#include "config.h"
+#include "vm/types.h"
+
 #include "mm/memory.h"
 #include "native/native.h"
 #include "native/include/java_lang_Throwable.h"
 #endif
 
 #include "toolbox/logging.h"
-#include "toolbox/util.h"
-#include "vm/exceptions.h"
 #include "vm/builtin.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/linker.h"
 #include "vm/loader.h"
 #include "vm/options.h"
 #include "vm/statistics.h"
 #include "vm/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/suck.h"
 
-#if defined(USE_ZLIB)
-# include "vm/unzip.h"
+#if defined(ENABLE_ZLIB)
+# include "vm/zip.h"
 #endif
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc.h"
+#include "vm/jit/codegen-common.h"
 
 
-#undef JOWENN_DEBUG
-#undef JOWENN_DEBUG1
-#undef JOWENN_DEBUG2
+/******************************************************************************/
+/* DEBUG HELPERS                                                              */
+/******************************************************************************/
 
+#ifndef NDEBUG
+#define LOADER_DEBUG
+#endif
 
-/********************************************************************
-   list of classpath entries (either filesystem directories or 
-   ZIP/JAR archives
-********************************************************************/
+#ifdef LOADER_DEBUG
+#define LOADER_ASSERT(cond)  assert(cond)
+#else
+#define LOADER_ASSERT(cond)
+#endif
 
-classpath_info *classpath_entries = NULL;
 
 /* loader_init *****************************************************************
 
@@ -97,565 +102,197 @@ classpath_info *classpath_entries = NULL;
  
 bool loader_init(u1 *stackbottom)
 {
-       classpath_info *cpi;
-
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       /* Initialize the monitor pointer for zip/jar file locking.               */
+       list_classpath_entry *lce;
 
-       for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
-               if (cpi->type == CLASSPATH_ARCHIVE)
-                       initObjectLock(&cpi->header);
-       }
+       /* Initialize the monitor pointer for zip/jar file locking. */
+
+       for (lce = list_first(list_classpath_entries); lce != NULL;
+                lce = list_next(list_classpath_entries, lce))
+               if (lce->type == CLASSPATH_ARCHIVE)
+                       initObjectLock((java_objectheader *) lce);
 #endif
 
        /* load some important classes */
 
-       if (!load_class_bootstrap(class_java_lang_Object))
+       if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_String))
+       if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Cloneable))
+       if (!(class_java_lang_Cloneable =
+                 load_class_bootstrap(utf_java_lang_Cloneable)))
                return false;
 
-       if (!load_class_bootstrap(class_java_io_Serializable))
+       if (!(class_java_io_Serializable =
+                 load_class_bootstrap(utf_java_io_Serializable)))
                return false;
 
 
        /* load classes for wrapping primitive types */
 
-       if (!load_class_bootstrap(class_java_lang_Void))
+       if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Boolean))
+       if (!(class_java_lang_Boolean =
+                 load_class_bootstrap(utf_java_lang_Boolean)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Byte))
+       if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Character))
+       if (!(class_java_lang_Character =
+                 load_class_bootstrap(utf_java_lang_Character)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Short))
+       if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Integer))
+       if (!(class_java_lang_Integer =
+                 load_class_bootstrap(utf_java_lang_Integer)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Long))
+       if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Float))
+       if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
                return false;
 
-       if (!load_class_bootstrap(class_java_lang_Double))
+       if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
                return false;
 
 
-#if defined(USE_THREADS)
-       if (stackbottom != 0)
-               initLocks();
-#endif
-
-       return true;
-}
-
-
-/************* functions for reading classdata *********************************
-
-    getting classdata in blocks of variable size
-    (8,16,32,64-bit integer or float)
-
-*******************************************************************************/
-
-/* check_classbuffer_size ******************************************************
-
-   assert that at least <len> bytes are left to read
-   <len> is limited to the range of non-negative s4 values
-
-*******************************************************************************/
-
-inline bool check_classbuffer_size(classbuffer *cb, s4 len)
-{
-       if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
-               *exceptionptr =
-                       new_classformaterror((cb)->class, "Truncated class file");
+       /* load some other important classes */
 
+       if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
                return false;
-       }
-
-       return true;
-}
-
-
-/* suck_nbytes *****************************************************************
-
-   transfer block of classfile data into a buffer
-
-*******************************************************************************/
-
-inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
-{
-       memcpy(buffer, cb->pos + 1, len);
-       cb->pos += len;
-}
-
-
-/* skip_nbytes ****************************************************************
-
-   skip block of classfile data
-
-*******************************************************************************/
-
-inline void skip_nbytes(classbuffer *cb, s4 len)
-{
-       cb->pos += len;
-}
-
-
-inline u1 suck_u1(classbuffer *cb)
-{
-       return *++(cb->pos);
-}
-
-
-inline u2 suck_u2(classbuffer *cb)
-{
-       u1 a = suck_u1(cb);
-       u1 b = suck_u1(cb);
-       return ((u2) a << 8) + (u2) b;
-}
-
-
-inline u4 suck_u4(classbuffer *cb)
-{
-       u1 a = suck_u1(cb);
-       u1 b = suck_u1(cb);
-       u1 c = suck_u1(cb);
-       u1 d = suck_u1(cb);
-       return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
-}
-
-
-/* get u8 from classfile data */
-static u8 suck_u8(classbuffer *cb)
-{
-#if U8_AVAILABLE
-       u8 lo, hi;
-       hi = suck_u4(cb);
-       lo = suck_u4(cb);
-       return (hi << 32) + lo;
-#else
-       u8 v;
-       v.high = suck_u4(cb);
-       v.low = suck_u4(cb);
-       return v;
-#endif
-}
-
-
-/* get float from classfile data */
-static float suck_float(classbuffer *cb)
-{
-       float f;
-
-#if !WORDS_BIGENDIAN 
-       u1 buffer[4];
-       u2 i;
-
-       for (i = 0; i < 4; i++)
-               buffer[3 - i] = suck_u1(cb);
-
-       memcpy((u1*) (&f), buffer, 4);
-#else
-       suck_nbytes((u1*) (&f), cb, 4);
-#endif
-
-       if (sizeof(float) != 4) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible float-format");
-
-               /* XXX should we exit in such a case? */
-               throw_exception_exit();
-       }
-       
-       return f;
-}
-
-
-/* get double from classfile data */
-static double suck_double(classbuffer *cb)
-{
-       double d;
-
-#if !WORDS_BIGENDIAN 
-       u1 buffer[8];
-       u2 i;   
-
-       for (i = 0; i < 8; i++)
-               buffer[7 - i] = suck_u1(cb);
-
-       memcpy((u1*) (&d), buffer, 8);
-#else 
-       suck_nbytes((u1*) (&d), cb, 8);
-#endif
-
-       if (sizeof(double) != 8) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible double-format");
-
-               /* XXX should we exit in such a case? */
-               throw_exception_exit();
-       }
-       
-       return d;
-}
-
-
-/************************** function suck_init *********************************
-
-       called once at startup, sets the searchpath for the classfiles
-
-*******************************************************************************/
-
-void suck_init(char *classpath)
-{
-       char           *start;
-       char           *end;
-       char           *filename;
-       s4              filenamelen;
-       bool            is_zip;
-       classpath_info *cpi;
-       classpath_info *lastcpi;
-       char           *cwd;
-       s4              cwdlen;
-
-       /* 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';) {
+       if (!(class_java_lang_ClassLoader =
+                 load_class_bootstrap(utf_java_lang_ClassLoader)))
+               return false;
 
-               /* search for ':' delimiter to get the end of the current entry */
-               for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+       if (!(class_java_lang_SecurityManager =
+                 load_class_bootstrap(utf_java_lang_SecurityManager)))
+               return false;
 
-               if (start != end) {
-                       is_zip = false;
-                       filenamelen = end - start;
+       if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
+               return false;
 
-                       if (filenamelen > 3) {
-                               if (strncasecmp(end - 3, "zip", 3) == 0 ||
-                                       strncasecmp(end - 3, "jar", 3) == 0) {
-                                       is_zip = true;
-                               }
-                       }
+       if (!(class_java_lang_Thread =
+                 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
+               return false;
 
-                       /* save classpath entries as absolute pathnames */
+       if (!(class_java_lang_ThreadGroup =
+                 load_class_bootstrap(utf_java_lang_ThreadGroup)))
+               return false;
 
-                       cwd = NULL;
-                       cwdlen = 0;
+       if (!(class_java_lang_VMThread =
+                 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
+               return false;
 
-                       if (*start != '/') {                      /* XXX fix me for win32 */
-                               cwd = _Jv_getcwd();
-                               cwdlen = strlen(cwd) + strlen("/");
-                       }
 
-                       /* allocate memory for filename and fill it */
+       /* some classes which may be used more often */
 
-                       filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
-                                                       strlen("0"));
+       if (!(class_java_lang_StackTraceElement =
+                 load_class_bootstrap(utf_java_lang_StackTraceElement)))
+               return false;
 
-                       if (cwd) {
-                               strcpy(filename, cwd);
-                               strcat(filename, "/");
-                               strncat(filename, start, filenamelen);
+       if (!(class_java_lang_reflect_Constructor =
+                 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
+               return false;
 
-                               /* add cwd length to file length */
-                               filenamelen += cwdlen;
+       if (!(class_java_lang_reflect_Field =
+                 load_class_bootstrap(utf_java_lang_reflect_Field)))
+               return false;
 
-                       } else {
-                               strncpy(filename, start, filenamelen);
-                               filename[filenamelen] = '\0';
-                       }
+       if (!(class_java_lang_reflect_Method =
+                 load_class_bootstrap(utf_java_lang_reflect_Method)))
+               return false;
 
-                       cpi = NULL;
+       if (!(class_java_security_PrivilegedAction =
+                 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
+               return false;
 
-                       if (is_zip) {
-#if defined(USE_ZLIB)
-                               unzFile uf = unzOpen(filename);
+       if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
+               return false;
 
-                               if (uf) {
-                                       cpi = NEW(classpath_info);
-                                       cpi->type = CLASSPATH_ARCHIVE;
-                                       cpi->uf = uf;
-                                       cpi->next = NULL;
-                                       cpi->path = filename;
-                                       cpi->pathlen = filenamelen;
-                               }
+       if (!(arrayclass_java_lang_Object =
+                 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
+               return false;
 
-#else
-                               throw_cacao_exception_exit(string_java_lang_InternalError,
-                                                                                  "zip/jar files not supported");
+#if defined(USE_THREADS)
+       if (stackbottom != 0)
+               initLocks();
 #endif
-                               
-                       } else {
-                               cpi = NEW(classpath_info);
-                               cpi->type = CLASSPATH_PATH;
-                               cpi->next = NULL;
-
-                               if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
-                                       filename[filenamelen] = '/';
-                                       filename[filenamelen + 1] = '\0';
-                                       filenamelen++;
-                               }
-
-                               cpi->path = filename;
-                               cpi->pathlen = filenamelen;
-                       }
-
-                       /* attach current classpath entry */
-
-                       if (cpi) {
-                               if (!classpath_entries)
-                                       classpath_entries = cpi;
-                               else
-                                       lastcpi->next = cpi;
-
-                               lastcpi = cpi;
-                       }
-               }
 
-               /* goto next classpath entry, skip ':' delimiter */
-
-               if ((*end) == ':') {
-                       start = end + 1;
-
-               } else {
-                       start = end;
-               }
-       }
+       return true;
 }
 
 
-void create_all_classes()
-{
-       classpath_info *cpi;
-
-       for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
-#if defined(USE_ZLIB)
-               if (cpi->type == CLASSPATH_ARCHIVE) {
-                       cacao_entry_s *ce;
-                       unz_s *s;
-
-                       s = (unz_s *) cpi->uf;
-                       ce = s->cacao_dir_list;
-                               
-                       while (ce) {
-                               (void) class_new(ce->name);
-                               ce = ce->next;
-                       }
-
-               } else {
-#endif
-#if defined(USE_ZLIB)
-               }
-#endif
-       }
-}
-
+/* loader_load_all_classes *****************************************************
 
-/* suck_start ******************************************************************
+   Loads all classes specified in the BOOTCLASSPATH.
 
-   Returns true if classbuffer is already loaded or a file for the
-   specified class has succussfully been read in. All directories of
-   the searchpath are used to find the classfile (<classname>.class).
-   Returns false if no classfile is found and writes an error message.
-       
 *******************************************************************************/
 
-classbuffer *suck_start(classinfo *c)
+void loader_load_all_classes(void)
 {
-       classpath_info *cpi;
-       char           *filename;
-       s4             filenamelen;
-       char *path;
-       FILE *classfile;
-       bool found;
-       s4 len;
-       struct stat buffer;
-       classbuffer *cb;
-
-       /* initialize return value */
-
-       found = false;
-       cb = NULL;
-
-       filenamelen = utf_strlen(c->name) + strlen(".class") + strlen("0");
-       filename = MNEW(char, filenamelen);
+       list_classpath_entry    *lce;
+       hashtable               *ht;
+       s4                       slot;
+       hashtable_zipfile_entry *htzfe;
+       utf                     *u;
 
-       utf_sprint(filename, c->name);
-       strcat(filename, ".class");
+       for (lce = list_first(list_classpath_entries); lce != NULL;
+                lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+               if (lce->type == CLASSPATH_ARCHIVE) {
+                       /* get the classes hashtable */
 
-       /* walk through all classpath entries */
+                       ht = lce->htclasses;
 
-       for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
-#if defined(USE_ZLIB)
-               if (cpi->type == CLASSPATH_ARCHIVE) {
+                       for (slot = 0; slot < ht->size; slot++) {
+                               htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
 
-#if defined(USE_THREADS)
-                       /* enter a monitor on zip/jar archives */
-
-                       builtin_monitorenter((java_objectheader *) cpi);
-#endif
+                               for (; htzfe; htzfe = htzfe->hashlink) {
+                                       u = htzfe->filename;
 
-                       if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
-                               unz_file_info file_info;
+                                       /* skip all entries in META-INF and .properties,
+                       .png files */
 
-                               if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
-                                                                                 sizeof(filename), NULL, 0, NULL, 0) == 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;
+                                       if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
+                                               strstr(u->text, ".properties") ||
+                                               strstr(u->text, ".png"))
+                                               continue;
 
-                                               len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
+                                       /* load class from bootstrap classloader */
 
-                                               if (len != cb->size) {
-                                                       suck_stop(cb);
-                                                       log_text("Error while unzipping");
+                                       if (!load_class_bootstrap(u)) {
+                                               fprintf(stderr, "Error loading: ");
+                                               utf_fprint_classname(stderr, u);
+                                               fprintf(stderr, "\n");
 
-                                               } else {
-                                                       found = true;
-                                               }
+                                               /* print out exception and cause */
 
-                                       } else {
-                                               log_text("Error while opening file in archive");
+                                               exceptions_print_exception(*exceptionptr);
                                        }
-
-                               } else {
-                                       log_text("Error while retrieving fileinfo");
                                }
                        }
-                       unzCloseCurrentFile(cpi->uf);
-
-#if defined(USE_THREADS)
-                       /* leave the monitor */
-
-                       builtin_monitorexit((java_objectheader *) cpi);
-#endif
 
                } else {
-#endif /* defined(USE_ZLIB) */
-                       
-                       path = MNEW(char, cpi->pathlen + filenamelen);
-                       strcpy(path, cpi->path);
-                       strcat(path, filename);
-
-                       classfile = fopen(path, "r");
-
-                       if (classfile) {                                   /* file exists */
-                               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;
-
-                                       /* read class data */
-                                       len = fread(cb->data, 1, cb->size, classfile);
-
-                                       if (len != buffer.st_size) {
-                                               suck_stop(cb);
-/*                                             if (ferror(classfile)) { */
-/*                                             } */
-
-                                       } else {
-                                               found = true;
-                                       }
-                               }
-                       }
-
-                       MFREE(path, char, cpi->pathlen + filenamelen);
-#if defined(USE_ZLIB)
+#endif
+#if defined(ENABLE_ZLIB)
                }
 #endif
        }
-
-       if (opt_verbose)
-               if (!found)
-                       dolog("Warning: Can not open class file '%s'", filename);
-
-       MFREE(filename, char, filenamelen);
-
-       return cb;
-}
-
-
-/************************** function suck_stop *********************************
-
-       frees memory for buffer with classfile data.
-       Caution: this function may only be called if buffer has been allocated
-                by suck_start with reading a file
-       
-*******************************************************************************/
-
-void suck_stop(classbuffer *cb)
-{
-       /* free memory */
-
-       MFREE(cb->data, u1, cb->size);
-       FREE(cb, classbuffer);
-}
-
-
-/******************************************************************************/
-/******************* Some support functions ***********************************/
-/******************************************************************************/
-
-void fprintflags (FILE *fp, u2 f)
-{
-   if ( f & ACC_PUBLIC )       fprintf (fp," PUBLIC");
-   if ( f & ACC_PRIVATE )      fprintf (fp," PRIVATE");
-   if ( f & ACC_PROTECTED )    fprintf (fp," PROTECTED");
-   if ( f & ACC_STATIC )       fprintf (fp," STATIC");
-   if ( f & ACC_FINAL )        fprintf (fp," FINAL");
-   if ( f & ACC_SYNCHRONIZED ) fprintf (fp," SYNCHRONIZED");
-   if ( f & ACC_VOLATILE )     fprintf (fp," VOLATILE");
-   if ( f & ACC_TRANSIENT )    fprintf (fp," TRANSIENT");
-   if ( f & ACC_NATIVE )       fprintf (fp," NATIVE");
-   if ( f & ACC_INTERFACE )    fprintf (fp," INTERFACE");
-   if ( f & ACC_ABSTRACT )     fprintf (fp," ABSTRACT");
-}
-
-
-/********** internal function: printflags  (only for debugging) ***************/
-
-void printflags(u2 f)
-{
-   if ( f & ACC_PUBLIC )       printf (" PUBLIC");
-   if ( f & ACC_PRIVATE )      printf (" PRIVATE");
-   if ( f & ACC_PROTECTED )    printf (" PROTECTED");
-   if ( f & ACC_STATIC )       printf (" STATIC");
-   if ( f & ACC_FINAL )        printf (" FINAL");
-   if ( f & ACC_SYNCHRONIZED ) printf (" SYNCHRONIZED");
-   if ( f & ACC_VOLATILE )     printf (" VOLATILE");
-   if ( f & ACC_TRANSIENT )    printf (" TRANSIENT");
-   if ( f & ACC_NATIVE )       printf (" NATIVE");
-   if ( f & ACC_INTERFACE )    printf (" INTERFACE");
-   if ( f & ACC_ABSTRACT )     printf (" ABSTRACT");
 }
 
 
-/********************** Function: skipattributebody ****************************
+/* skipattributebody ***********************************************************
 
-       skips an attribute after the 16 bit reference to attribute_name has already
-       been read
+   Skips an attribute after the 16 bit reference to attribute_name has
+   already been read.
        
 *******************************************************************************/
 
@@ -663,15 +300,15 @@ static bool skipattributebody(classbuffer *cb)
 {
        u4 len;
 
-       if (!check_classbuffer_size(cb, 4))
+       if (!suck_check_classbuffer_size(cb, 4))
                return false;
 
        len = suck_u4(cb);
 
-       if (!check_classbuffer_size(cb, len))
+       if (!suck_check_classbuffer_size(cb, len))
                return false;
 
-       skip_nbytes(cb, len);
+       suck_skip_nbytes(cb, len);
 
        return true;
 }
@@ -689,87 +326,22 @@ static bool skipattributes(classbuffer *cb, u4 num)
        u4 len;
 
        for (i = 0; i < num; i++) {
-               if (!check_classbuffer_size(cb, 2 + 4))
+               if (!suck_check_classbuffer_size(cb, 2 + 4))
                        return false;
 
                suck_u2(cb);
                len = suck_u4(cb);
 
-               if (!check_classbuffer_size(cb, len))
+               if (!suck_check_classbuffer_size(cb, len))
                        return false;
 
-               skip_nbytes(cb, len);
+               suck_skip_nbytes(cb, len);
        }
 
        return true;
 }
 
 
-/******************** function:: class_getconstant *****************************
-
-       retrieves the value at position 'pos' of the constantpool of a class
-       if the type of the value is other than 'ctype' the system is stopped
-
-*******************************************************************************/
-
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
-       /* check index and type of constantpool entry */
-       /* (pos == 0 is caught by type comparison) */
-       if (pos >= c->cpcount || c->cptags[pos] != ctype) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
-               return NULL;
-       }
-
-       return c->cpinfos[pos];
-}
-
-
-/******************** function: innerclass_getconstant ************************
-
-    like class_getconstant, but if cptags is ZERO null is returned
-       
-*******************************************************************************/
-
-voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
-       /* invalid position in constantpool */
-       if (pos >= c->cpcount) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
-               return NULL;
-       }
-
-       /* constantpool entry of type 0 */      
-       if (!c->cptags[pos])
-               return NULL;
-
-       /* check type of constantpool entry */
-       if (c->cptags[pos] != ctype) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
-               return NULL;
-       }
-               
-       return c->cpinfos[pos];
-}
-
-
-/********************* Function: class_constanttype ****************************
-
-       Determines the type of a class entry in the ConstantPool
-       
-*******************************************************************************/
-
-u4 class_constanttype(classinfo *c, u4 pos)
-{
-       if (pos <= 0 || pos >= c->cpcount) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
-               return 0;
-       }
-
-       return c->cptags[pos];
-}
-
-
 /* load_constantpool ***********************************************************
 
    Loads the constantpool of a class, the entries are transformed into
@@ -778,7 +350,7 @@ u4 class_constanttype(classinfo *c, u4 pos)
 
 *******************************************************************************/
 
-static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
+static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 {
 
        /* The following structures are used to save information which cannot be 
@@ -838,7 +410,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
        c = cb->class;
 
        /* number of entries in the constant_pool table plus one */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                return false;
 
        cpcount = c->cpcount = suck_u2(cb);
@@ -848,11 +420,11 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
        cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
 
        if (cpcount < 1) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
+               exceptions_throw_classformaterror(c, "Illegal constant pool size");
                return false;
        }
        
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
 #endif
@@ -873,21 +445,21 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                u4 t;
 
                /* get constant type */
-               if (!check_classbuffer_size(cb, 1))
+               if (!suck_check_classbuffer_size(cb, 1))
                        return false;
 
                t = suck_u1(cb);
 
                switch (t) {
                case CONSTANT_Class:
-                       nfc = NEW(forward_class);
+                       nfc = DNEW(forward_class);
 
                        nfc->next = forward_classes;
                        forward_classes = nfc;
 
                        nfc->thisindex = idx;
                        /* reference to CONSTANT_NameAndType */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        nfc->name_index = suck_u2(cb);
@@ -896,7 +468,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        break;
                        
                case CONSTANT_String:
-                       nfs = NEW(forward_string);
+                       nfs = DNEW(forward_string);
                                
                        nfs->next = forward_strings;
                        forward_strings = nfs;
@@ -904,7 +476,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        nfs->thisindex = idx;
 
                        /* reference to CONSTANT_Utf8_info with string characters */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        nfs->string_index = suck_u2(cb);
@@ -913,14 +485,14 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        break;
 
                case CONSTANT_NameAndType:
-                       nfn = NEW(forward_nameandtype);
+                       nfn = DNEW(forward_nameandtype);
                                
                        nfn->next = forward_nameandtypes;
                        forward_nameandtypes = nfn;
                                
                        nfn->thisindex = idx;
 
-                       if (!check_classbuffer_size(cb, 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* reference to CONSTANT_Utf8_info containing simple name */
@@ -936,7 +508,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                case CONSTANT_Fieldref:
                case CONSTANT_Methodref:
                case CONSTANT_InterfaceMethodref:
-                       nff = NEW(forward_fieldmethint);
+                       nff = DNEW(forward_fieldmethint);
                        
                        nff->next = forward_fieldmethints;
                        forward_fieldmethints = nff;
@@ -945,7 +517,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        /* constant type */
                        nff->tag = t;
 
-                       if (!check_classbuffer_size(cb, 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 2 + 2))
                                return false;
 
                        /* class or interface type that contains the declaration of the
@@ -961,12 +533,12 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                case CONSTANT_Integer: {
                        constant_integer *ci = NEW(constant_integer);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                        if (opt_stat)
                                count_const_pool_len += sizeof(constant_integer);
 #endif
 
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                return false;
 
                        ci->value = suck_s4(cb);
@@ -980,12 +552,12 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                case CONSTANT_Float: {
                        constant_float *cf = NEW(constant_float);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                        if (opt_stat)
                                count_const_pool_len += sizeof(constant_float);
 #endif
 
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                return false;
 
                        cf->value = suck_float(cb);
@@ -999,12 +571,12 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                case CONSTANT_Long: {
                        constant_long *cl = NEW(constant_long);
                                        
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                        if (opt_stat)
                                count_const_pool_len += sizeof(constant_long);
 #endif
 
-                       if (!check_classbuffer_size(cb, 8))
+                       if (!suck_check_classbuffer_size(cb, 8))
                                return false;
 
                        cl->value = suck_s8(cb);
@@ -1012,8 +584,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        cpinfos[idx] = cl;
                        idx += 2;
                        if (idx > cpcount) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Invalid constant pool entry");
+                               exceptions_throw_classformaterror(c, "Invalid constant pool entry");
                                return false;
                        }
                        break;
@@ -1022,12 +593,12 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                case CONSTANT_Double: {
                        constant_double *cd = NEW(constant_double);
                                
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                        if (opt_stat)
                                count_const_pool_len += sizeof(constant_double);
 #endif
 
-                       if (!check_classbuffer_size(cb, 8))
+                       if (!suck_check_classbuffer_size(cb, 8))
                                return false;
 
                        cd->value = suck_double(cb);
@@ -1035,8 +606,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        cpinfos[idx] = cd;
                        idx += 2;
                        if (idx > cpcount) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Invalid constant pool entry");
+                               exceptions_throw_classformaterror(c, "Invalid constant pool entry");
                                return false;
                        }
                        break;
@@ -1046,87 +616,85 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                        u4 length;
 
                        /* number of bytes in the bytes array (not string-length) */
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        length = suck_u2(cb);
                        cptags[idx] = CONSTANT_Utf8;
 
                        /* validate the string */
-                       if (!check_classbuffer_size(cb, length))
+                       if (!suck_check_classbuffer_size(cb, length))
                                return false;
 
+#ifdef ENABLE_VERIFIER
                        if (opt_verify &&
-                               !is_valid_utf((char *) (cb->pos + 1),
-                                                         (char *) (cb->pos + 1 + length))) {
-                               dolog("Invalid UTF-8 string (constant pool index %d)",idx);
-                               panic("Invalid UTF-8 string");
+                               !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length))) 
+                       {
+                               exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
+                               return false;
                        }
+#endif /* ENABLE_VERIFIER */
                        /* insert utf-string into the utf-symboltable */
-                       cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
+                       cpinfos[idx] = utf_new((char *) cb->pos, length);
 
                        /* skip bytes of the string (buffer size check above) */
-                       skip_nbytes(cb, length);
+                       suck_skip_nbytes(cb, length);
                        idx++;
                        break;
                }
                                                                                
                default:
-                       *exceptionptr =
-                               new_classformaterror(c, "Illegal constant pool type");
+                       exceptions_throw_classformaterror(c, "Illegal constant pool type");
                        return false;
                }  /* end switch */
        } /* end while */
 
-       /* add all class references to the descriptor_pool */
-       for (nfc=forward_classes; nfc; nfc=nfc->next) {
-               utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
-               if (!descriptor_pool_add_class(descpool,name))
-                       return false;
-       }
-       /* add all descriptors in NameAndTypes to the descriptor_pool */
-       for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
-               utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
-               if (!descriptor_pool_add(descpool,desc,NULL))
-                       return false;
-       }
 
        /* resolve entries in temporary structures */
 
        while (forward_classes) {
                utf *name =
                        class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+               if (!name)
+                       return false;
+
+#ifdef ENABLE_VERIFIER
+               if (opt_verify && !is_valid_name_utf(name)) {
+                       exceptions_throw_classformaterror(c, "Class reference with invalid name");
+                       return false;
+               }
+#endif /* ENABLE_VERIFIER */
 
-               if (opt_verify && !is_valid_name_utf(name))
-                       panic("Class reference with invalid name");
+               /* add all class references to the descriptor_pool */
+
+               if (!descriptor_pool_add_class(descpool, name))
+                       return false;
 
                cptags[forward_classes->thisindex] = CONSTANT_Class;
-               /* retrieve class from class-table */
+
                if (opt_eager) {
                        classinfo *tc;
-                       tc = class_new_intern(name);
 
-                       if (!load_class_from_classloader(tc, c->classloader))
+                       if (!(tc = load_class_bootstrap(name)))
                                return false;
 
                        /* link the class later, because we cannot link the class currently
                           loading */
                        list_addfirst(&unlinkedclasses, tc);
-
-                       cpinfos[forward_classes->thisindex] = tc;
-
-               } else {
-                       cpinfos[forward_classes->thisindex] = class_new(name);
                }
 
+               /* the classref is created later */
+               cpinfos[forward_classes->thisindex] = name;
+
                nfc = forward_classes;
                forward_classes = forward_classes->next;
-               FREE(nfc, forward_class);
        }
 
        while (forward_strings) {
                utf *text =
                        class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+               if (!text)
+                       return false;
 
                /* resolve utf-string */
                cptags[forward_strings->thisindex] = CONSTANT_String;
@@ -1134,13 +702,12 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                
                nfs = forward_strings;
                forward_strings = forward_strings->next;
-               FREE(nfs, forward_string);
        }
 
        while (forward_nameandtypes) {
                constant_nameandtype *cn = NEW(constant_nameandtype);   
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                if (opt_stat)
                        count_const_pool_len += sizeof(constant_nameandtype);
 #endif
@@ -1149,55 +716,65 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
                cn->name = class_getconstant(c,
                                                                         forward_nameandtypes->name_index,
                                                                         CONSTANT_Utf8);
+               if (!cn->name)
+                       return false;
 
                cn->descriptor = class_getconstant(c,
                                                                                   forward_nameandtypes->sig_index,
                                                                                   CONSTANT_Utf8);
+               if (!cn->descriptor)
+                       return false;
 
+#ifdef ENABLE_VERIFIER
                if (opt_verify) {
                        /* check name */
                        if (!is_valid_name_utf(cn->name)) {
-                               *exceptionptr =
-                                       new_classformaterror(c,
-                                                                                "Illegal Field name \"%s\"",
-                                                                                cn->name->text);
+                               exceptions_throw_classformaterror(c,
+                                                                                                 "Illegal Field name \"%s\"",
+                                                                                                 cn->name->text);
 
                                return false;
                        }
 
                        /* disallow referencing <clinit> among others */
                        if (cn->name->text[0] == '<' && cn->name != utf_init) {
-                               *exceptionptr =
-                                       new_exception_utfmessage(string_java_lang_InternalError,
-                                                                                        cn->name);
+                               exceptions_throw_classformaterror(c, "Illegal reference to special method");
                                return false;
                        }
                }
+#endif /* ENABLE_VERIFIER */
 
                cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
                cpinfos[forward_nameandtypes->thisindex] = cn;
 
                nfn = forward_nameandtypes;
                forward_nameandtypes = forward_nameandtypes->next;
-               FREE(nfn, forward_nameandtype);
        }
 
        while (forward_fieldmethints) {
                constant_nameandtype *nat;
                constant_FMIref *fmi = NEW(constant_FMIref);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                if (opt_stat)
                        count_const_pool_len += sizeof(constant_FMIref);
 #endif
                /* resolve simple name and descriptor */
+
                nat = class_getconstant(c,
                                                                forward_fieldmethints->nameandtype_index,
                                                                CONSTANT_NameAndType);
+               if (!nat)
+                       return false;
+
+               /* add all descriptors in {Field,Method}ref to the descriptor_pool */
+
+               if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
+                       return false;
+
+               /* the classref is created later */
 
-               fmi->class = class_getconstant(c,
-                                                                          forward_fieldmethints->class_index,
-                                                                          CONSTANT_Class);
+               fmi->classref = (constant_classref *) (size_t) forward_fieldmethints->class_index;
                fmi->name = nat->name;
                fmi->descriptor = nat->descriptor;
 
@@ -1206,7 +783,6 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
        
                nff = forward_fieldmethints;
                forward_fieldmethints = forward_fieldmethints->next;
-               FREE(nff, forward_fieldmethint);
        }
 
        /* everything was ok */
@@ -1225,7 +801,7 @@ static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
 
 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
 
-static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
+static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
 {
        classinfo *c;
        u4 attrnum, i;
@@ -1235,28 +811,39 @@ static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
 
        c = cb->class;
 
-       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
                return false;
 
        f->flags = suck_u2(cb);
 
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
+
        f->name = u;
 
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
+
        f->descriptor = u;
        f->parseddesc = NULL;
-       if (!descriptor_pool_add(descpool,u,NULL))
+
+       if (!descriptor_pool_add(descpool, u, NULL))
+               return false;
+
+       /* descriptor_pool_add accepts method descriptors, so we have to check  */
+       /* against them here before the call of descriptor_to_basic_type below. */
+       if (u->text[0] == '(') {
+               exceptions_throw_classformaterror(c, "Method descriptor used for field");
                return false;
+       }
 
+#ifdef ENABLE_VERIFIER
        if (opt_verify) {
                /* check name */
                if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
-                       *exceptionptr = new_classformaterror(c,
-                                                                                                "Illegal Field name \"%s\"",
-                                                                                                f->name->text);
+                       exceptions_throw_classformaterror(c,
+                                                                                         "Illegal Field name \"%s\"",
+                                                                                         f->name->text);
                        return false;
                }
 
@@ -1265,10 +852,9 @@ static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
 
                if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
                        ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
-                       *exceptionptr =
-                               new_classformaterror(c,
-                                                                        "Illegal field modifiers: 0x%X",
-                                                                        f->flags);
+                       exceptions_throw_classformaterror(c,
+                                                                                         "Illegal field modifiers: 0x%X",
+                                                                                         f->flags);
                        return false;
                }
 
@@ -1276,17 +862,17 @@ static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
                        if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
                                != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
                                f->flags & ACC_TRANSIENT) {
-                               *exceptionptr =
-                                       new_classformaterror(c,
-                                                                                "Illegal field modifiers: 0x%X",
-                                                                                f->flags);
+                               exceptions_throw_classformaterror(c,
+                                                                                                 "Illegal field modifiers: 0x%X",
+                                                                                                 f->flags);
                                return false;
                        }
                }
        }
+#endif /* ENABLE_VERIFIER */
                
-       f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
-       f->offset = 0;                             /* offset from start of object */
+       f->type = jtype = descriptor_to_basic_type(f->descriptor); /* data type */
+       f->offset = 0;                           /* offset from start of object */
        f->class = c;
        f->xta = NULL;
        
@@ -1304,33 +890,30 @@ static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
        }
 
        /* read attributes */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                return false;
 
        attrnum = suck_u2(cb);
        for (i = 0; i < attrnum; i++) {
-               if (!check_classbuffer_size(cb, 2))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                        return false;
 
                if (u == utf_ConstantValue) {
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        /* check attribute length */
                        if (suck_u4(cb) != 2) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Wrong size for VALUE attribute");
+                               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
                                return false;
                        }
                        
                        /* constant value attribute */
                        if (pindex != field_load_NOVALUE) {
-                               *exceptionptr =
-                                       new_classformaterror(c,
-                                                                                "Multiple ConstantValue attributes");
+                               exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
                                return false;
                        }
                        
@@ -1413,7 +996,7 @@ static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
        
 *******************************************************************************/
 
-static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
+static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 {
        classinfo *c;
        int argcount;
@@ -1428,7 +1011,7 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
        initObjectLock(&m->header);
 #endif
 
-#ifdef STATISTICS
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_all_methods++;
 #endif
@@ -1439,38 +1022,47 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
        m->class = c;
        m->nativelyoverloaded = false;
        
-       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
                return false;
 
        m->flags = suck_u2(cb);
 
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
+
        m->name = u;
 
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
+
        m->descriptor = u;
        m->parseddesc = NULL;
-       if (!descriptor_pool_add(descpool,u,&argcount))
+
+       if (!descriptor_pool_add(descpool, u, &argcount))
                return false;
 
+#ifdef ENABLE_VERIFIER
        if (opt_verify) {
-               if (!is_valid_name_utf(m->name))
-                       panic("Method with invalid name");
+               if (!is_valid_name_utf(m->name)) {
+                       exceptions_throw_classformaterror(c, "Method with invalid name");
+                       return false;
+               }
 
-               if (m->name->text[0] == '<'
-                       && m->name != utf_init && m->name != utf_clinit)
-                       panic("Method with invalid special name");
+               if (m->name->text[0] == '<' &&
+                       m->name != utf_init && m->name != utf_clinit) {
+                       exceptions_throw_classformaterror(c, "Method with invalid special name");
+                       return false;
+               }
        }
+#endif /* ENABLE_VERIFIER */
        
        if (!(m->flags & ACC_STATIC))
                argcount++; /* count the 'this' argument */
 
+#ifdef ENABLE_VERIFIER
        if (opt_verify) {
                if (argcount > 255) {
-                       *exceptionptr =
-                               new_classformaterror(c, "Too many arguments in signature");
+                       exceptions_throw_classformaterror(c, "Too many arguments in signature");
                        return false;
                }
 
@@ -1479,41 +1071,41 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
                        i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
 
                        if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
-                               *exceptionptr =
-                                       new_classformaterror(c,
-                                                                                "Illegal method modifiers: 0x%X",
-                                                                                m->flags);
+                               exceptions_throw_classformaterror(c,
+                                                                                                 "Illegal method modifiers: 0x%X",
+                                                                                                 m->flags);
                                return false;
                        }
 
                        if (m->flags & ACC_ABSTRACT) {
                                if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
                                                                 ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
-                                       *exceptionptr =
-                                               new_classformaterror(c,
-                                                                                        "Illegal method modifiers: 0x%X",
-                                                                                        m->flags);
+                                       exceptions_throw_classformaterror(c,
+                                                                                                         "Illegal method modifiers: 0x%X",
+                                                                                                         m->flags);
                                        return false;
                                }
                        }
 
                        if (c->flags & ACC_INTERFACE) {
                                if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
-                                       *exceptionptr =
-                                               new_classformaterror(c,
-                                                                                        "Illegal method modifiers: 0x%X",
-                                                                                        m->flags);
+                                       exceptions_throw_classformaterror(c,
+                                                                                                         "Illegal method modifiers: 0x%X",
+                                                                                                         m->flags);
                                        return false;
                                }
                        }
 
                        if (m->name == utf_init) {
                                if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
-                                                               ACC_NATIVE | ACC_ABSTRACT))
-                                       panic("Instance initialization method has invalid flags set");
+                                                               ACC_NATIVE | ACC_ABSTRACT)) {
+                                       exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
+                                       return false;
+                               }
                        }
                }
        }
+#endif /* ENABLE_VERIFIER */
                
        m->jcode = NULL;
        m->basicblockcount = 0;
@@ -1534,14 +1126,14 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
 
        m->xta = NULL;
 
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                return false;
        
        attrnum = suck_u2(cb);
        for (i = 0; i < attrnum; i++) {
                utf *aname;
 
-               if (!check_classbuffer_size(cb, 2))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1549,21 +1141,16 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
 
                if (aname == utf_Code) {
                        if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
-                                       *exceptionptr =
-                                               new_classformaterror(c,
-                                                                                        "Code attribute in native or abstract methods");
-
-                                       return false;
+                               exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
+                               return false;
                        }
                        
                        if (m->jcode) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Multiple Code attributes");
-
+                               exceptions_throw_classformaterror(c, "Multiple Code attributes");
                                return false;
                        }
 
-                       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
                                return false;
 
                        suck_u4(cb);
@@ -1571,51 +1158,45 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
                        m->maxlocals = suck_u2(cb);
 
                        if (m->maxlocals < argcount) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Arguments can't fit into locals");
-
+                               exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
                                return false;
                        }
                        
-                       if (!check_classbuffer_size(cb, 4))
+                       if (!suck_check_classbuffer_size(cb, 4))
                                return false;
 
                        m->jcodelength = suck_u4(cb);
 
                        if (m->jcodelength == 0) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Code of a method has length 0");
-
+                               exceptions_throw_classformaterror(c, "Code of a method has length 0");
                                return false;
                        }
                        
                        if (m->jcodelength > 65535) {
-                               *exceptionptr =
-                                       new_classformaterror(c,
-                                                                                "Code of a method longer than 65535 bytes");
-
+                               exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
                                return false;
                        }
 
-                       if (!check_classbuffer_size(cb, m->jcodelength))
+                       if (!suck_check_classbuffer_size(cb, m->jcodelength))
                                return false;
 
                        m->jcode = MNEW(u1, m->jcodelength);
                        suck_nbytes(m->jcode, cb, m->jcodelength);
 
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        m->exceptiontablelength = suck_u2(cb);
-                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
+                       if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
                                return false;
 
                        m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
                        if (opt_stat) {
                                count_vmcode_len += m->jcodelength + 18;
-                               count_extable_len += 8 * m->exceptiontablelength;
+                               count_extable_len +=
+                                       m->exceptiontablelength * sizeof(exceptiontable);
                        }
 #endif
 
@@ -1627,16 +1208,17 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
 
                                idx = suck_u2(cb);
                                if (!idx) {
-                                       m->exceptiontable[j].catchtype = NULL;
+                                       m->exceptiontable[j].catchtype.any = NULL;
 
                                } else {
-                                       if (!(m->exceptiontable[j].catchtype =
-                                                 class_getconstant(c, idx, CONSTANT_Class)))
+                                       /* the classref is created later */
+                                       if (!(m->exceptiontable[j].catchtype.any =
+                                                 (utf*)class_getconstant(c, idx, CONSTANT_Class)))
                                                return false;
                                }
                        }
 
-                       if (!check_classbuffer_size(cb, 2))
+                       if (!suck_check_classbuffer_size(cb, 2))
                                return false;
 
                        codeattrnum = suck_u2(cb);
@@ -1644,7 +1226,7 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
                        for (; codeattrnum > 0; codeattrnum--) {
                                utf *caname;
 
-                               if (!check_classbuffer_size(cb, 2))
+                               if (!suck_check_classbuffer_size(cb, 2))
                                        return false;
 
                                if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1653,13 +1235,13 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
                                if (caname == utf_LineNumberTable) {
                                        u2 lncid;
 
-                                       if (!check_classbuffer_size(cb, 4 + 2))
+                                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                                return false;
 
                                        suck_u4(cb);
                                        m->linenumbercount = suck_u2(cb);
 
-                                       if (!check_classbuffer_size(cb,
+                                       if (!suck_check_classbuffer_size(cb,
                                                                                                (2 + 2) * m->linenumbercount))
                                                return false;
 
@@ -1686,25 +1268,25 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
                        s4 j;
 
                        if (m->thrownexceptions) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Multiple Exceptions attributes");
+                               exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
                                return false;
                        }
 
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        suck_u4(cb); /* length */
                        m->thrownexceptionscount = suck_u2(cb);
 
-                       if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
+                       if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
                                return false;
 
-                       m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
+                       m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
 
                        for (j = 0; j < m->thrownexceptionscount; j++) {
-                               if (!((m->thrownexceptions)[j] =
-                                         class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+                               /* the classref is created later */
+                               if (!((m->thrownexceptions)[j].any =
+                                         (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
                                        return false;
                        }
                                
@@ -1715,8 +1297,7 @@ static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool
        }
 
        if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
-               *exceptionptr = new_classformaterror(c, "Missing Code attribute");
-
+               exceptions_throw_classformaterror(c, "Missing Code attribute");
                return false;
        }
 
@@ -1742,7 +1323,7 @@ static bool load_attributes(classbuffer *cb, u4 num)
 
        for (i = 0; i < num; i++) {
                /* retrieve attribute name */
-               if (!check_classbuffer_size(cb, 2))
+               if (!suck_check_classbuffer_size(cb, 2))
                        return false;
 
                if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
@@ -1751,12 +1332,11 @@ static bool load_attributes(classbuffer *cb, u4 num)
                if (aname == utf_InnerClasses) {
                        /* innerclasses attribute */
                        if (c->innerclass) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Multiple InnerClasses attributes");
+                               exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
                                return false;
                        }
                                
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        /* skip attribute length */
@@ -1765,7 +1345,7 @@ static bool load_attributes(classbuffer *cb, u4 num)
                        /* number of records */
                        c->innerclasscount = suck_u2(cb);
 
-                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+                       if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
                                return false;
 
                        /* allocate memory for innerclass structure */
@@ -1780,9 +1360,9 @@ static bool load_attributes(classbuffer *cb, u4 num)
                                                                
                                innerclassinfo *info = c->innerclass + j;
 
-                               info->inner_class =
+                               info->inner_class.ref =
                                        innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
-                               info->outer_class =
+                               info->outer_class.ref =
                                        innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
                                info->name =
                                        innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
@@ -1790,18 +1370,16 @@ static bool load_attributes(classbuffer *cb, u4 num)
                        }
 
                } else if (aname == utf_SourceFile) {
-                       if (!check_classbuffer_size(cb, 4 + 2))
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
                                return false;
 
                        if (suck_u4(cb) != 2) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Wrong size for VALUE attribute");
+                               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
                                return false;
                        }
 
                        if (c->sourcefile) {
-                               *exceptionptr =
-                                       new_classformaterror(c, "Multiple SourceFile attributes");
+                               exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
                                return false;
                        }
 
@@ -1819,20 +1397,152 @@ static bool load_attributes(classbuffer *cb, u4 num)
 }
 
 
-/* load_class_from_classloader *************************************************
+/* load_class_from_sysloader ***************************************************
+
+   Load the class with the given name using the system class loader
+
+   IN:
+       name.............the classname
+
+   RETURN VALUE:
+       the loaded class, or
+          NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *load_class_from_sysloader(utf *name)
+{
+       methodinfo        *m;
+       java_objectheader *cl;
+       classinfo         *c;
 
-   XXX
+       LOADER_ASSERT(class_java_lang_Object);
+       LOADER_ASSERT(class_java_lang_ClassLoader);
+       LOADER_ASSERT(class_java_lang_ClassLoader->state & CLASS_LINKED);
        
+       m = class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                utf_getSystemClassLoader,
+                                                                utf_void__java_lang_ClassLoader,
+                                                                class_java_lang_Object,
+                                                                false);
+
+       if (!m)
+               return false;
+
+       ASM_CALLJAVAFUNCTION_ADR(cl, m, NULL, NULL, NULL, NULL);
+
+       if (!cl)
+               return false;
+
+       c = load_class_from_classloader(name, cl);
+
+       return c;
+}
+
+
+/* load_class_from_classloader *************************************************
+
+   Load the class with the given name using the given user-defined class loader.
+
+   IN:
+       name.............the classname
+          cl...............user-defined class loader
+          
+   RETURN VALUE:
+       the loaded class, or
+          NULL if an exception has been thrown
+
 *******************************************************************************/
 
-classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
+classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 {
-       classinfo *r;
+       java_objectheader *o;
+       classinfo         *c;
+       classinfo         *tmpc;
+
+       LOADER_ASSERT(name);
+
+       /* lookup if this class has already been loaded */
+
+       c = classcache_lookup(cl, name);
+
+       if (c)
+               return c;
 
        /* if other class loader than bootstrap, call it */
 
        if (cl) {
                methodinfo *lc;
+               char       *text;
+               s4          namelen;
+
+               text = name->text;
+               namelen = name->blength;
+
+               /* handle array classes */
+               if (text[0] == '[') {
+                       classinfo *comp;
+                       utf       *u;
+
+                       switch (text[1]) {
+                       case 'L':
+                               /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+                               if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+                                       *exceptionptr = new_noclassdeffounderror(name);
+                                       return false;
+                               }
+
+                               u = utf_new(text + 2, namelen - 3);
+
+                               if (!(comp = load_class_from_classloader(u, cl)))
+                                       return false;
+
+                               /* create the array class */
+
+                               c = class_array_of(comp, false);
+
+                               tmpc = classcache_store(cl, c, true);
+
+                               if (tmpc == NULL) {
+                                       /* exception, free the loaded class */
+                                       c->state &= ~CLASS_LOADING;
+                                       class_free(c);
+                               }
+
+                               return tmpc;
+
+                       case '[':
+                               /* load the component class */
+
+                               u = utf_new(text + 1, namelen - 1);
+
+                               if (!(comp = load_class_from_classloader(u, cl)))
+                                       return false;
+
+                               /* create the array class */
+
+                               c = class_array_of(comp, false);
+
+                               tmpc = classcache_store(cl, c, true);
+
+                               if (tmpc == NULL) {
+                                       /* exception, free the loaded class */
+                                       c->state &= ~CLASS_LOADING;
+                                       class_free(c);
+                               }
+
+                               return tmpc;
+
+                       default:
+                               /* primitive array classes are loaded by the bootstrap loader */
+
+                               c = load_class_bootstrap(name);
+
+                               return c;
+                       }
+               }
+               
+               LOADER_ASSERT(class_java_lang_Object);
 
                lc = class_resolveclassmethod(cl->vftbl->class,
                                                                          utf_loadClass,
@@ -1841,49 +1551,107 @@ classinfo *load_class_from_classloader(classinfo *c, java_objectheader *cl)
                                                                          true);
 
                if (!lc)
-                       return NULL;
+                       return false; /* exception */
 
-               r = (classinfo *) asm_calljavafunction(lc,
-                                                                                          cl,
-                                                                                          javastring_new(c->name),
-                                                                                          NULL, NULL);
+               /* move return value into `o' and cast it afterwards to a classinfo* */
 
-               return r;
+               ASM_CALLJAVAFUNCTION_ADR(o, lc, cl,
+                                                                javastring_new_slash_to_dot(name),
+                                                                NULL, NULL);
 
-       } else {
-               return load_class_bootstrap(c);
-       }
+               c = (classinfo *) o;
+
+               if (c) {
+                       /* Store this class in the loaded class cache. If another
+                          class with the same (initloader,name) pair has been
+                          stored earlier it will be returned by classcache_store
+                          In this case classcache_store may not free the class
+                          because it has already been exposed to Java code which
+                          may have kept references to that class. */
+
+                   tmpc = classcache_store(cl, c, false);
+
+                       if (tmpc == NULL) {
+                               /* exception, free the loaded class */
+                               c->state &= ~CLASS_LOADING;
+                               class_free(c);
+                       }
+
+                       c = tmpc;
+
+               } else {
+                       /* loadClass has thrown an exception */
+                       /* we must convert ClassNotFoundException into NoClassDefFoundException */
+                       /* XXX maybe we should have a flag that avoids this conversion */
+                       /* for calling load_class_from_classloader from Class.forName  */
+                       /* Currently we do a double conversion in these cases          */
+                       classnotfoundexception_to_noclassdeffounderror();
+               }
+
+               /* SUN compatible -verbose:class output */
+
+               if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
+                       printf("[Loaded ");
+                       utf_display_classname(name);
+                       printf("]\n");
+               }
+
+               return c;
+       } 
+
+       c = load_class_bootstrap(name);
+
+       return c;
 }
 
 
 /* load_class_bootstrap ********************************************************
        
-   XXX
+   Load the class with the given name using the bootstrap class loader.
+
+   IN:
+       name.............the classname
+
+   RETURN VALUE:
+       loaded classinfo, or
+          NULL if an exception has been thrown
+
+   SYNCHRONIZATION:
+       load_class_bootstrap is synchronized. It can be treated as an
+          atomic operation.
 
 *******************************************************************************/
 
-classinfo *load_class_bootstrap(classinfo *c)
+classinfo *load_class_bootstrap(utf *name)
 {
        classbuffer *cb;
-       classinfo *r;
+       classinfo   *c;
+       classinfo   *r;
 
-#if defined(USE_THREADS)
-       /* enter a monitor on the class */
+       /* for debugging */
 
-       builtin_monitorenter((java_objectheader *) c);
-#endif
+       LOADER_ASSERT(name);
 
-       /* maybe the class is already loaded */
+       /* lookup if this class has already been loaded */
 
-       if (c->loaded) {
-#if defined(USE_THREADS)
-               builtin_monitorexit((java_objectheader *) c);
-#endif
+       if ((r = classcache_lookup(NULL, name)))
+               return r;
 
+       /* create the classinfo */
+
+       c = class_create_classinfo(name);
+       
+       /* handle array classes */
+
+       if (name->text[0] == '[') {
+               c = load_newly_created_array(c, NULL);
+               if (c == NULL)
+                       return NULL;
+               LOADER_ASSERT(c->state & CLASS_LOADED);
                return c;
        }
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getcompilingtime)
@@ -1896,18 +1664,13 @@ classinfo *load_class_bootstrap(classinfo *c)
        /* load classdata, throw exception on error */
 
        if ((cb = suck_start(c)) == NULL) {
-               /* this means, the classpath was not set properly */
-               if (c->name == utf_java_lang_Object)
+               /* this normally means, the classpath was not set properly */
+
+               if (name == utf_java_lang_Object)
                        throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
                                                                           "java/lang/Object");
 
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
-                                                                        c->name);
-
-#if defined(USE_THREADS)
-               builtin_monitorexit((java_objectheader *) c);
-#endif
+               *exceptionptr = new_noclassdeffounderror(name);
 
                return NULL;
        }
@@ -1916,18 +1679,39 @@ classinfo *load_class_bootstrap(classinfo *c)
 
        r = load_class_from_classbuffer(cb);
 
-       /* if return value is NULL, we had a problem and the class is not loaded */
        if (!r) {
-               c->loaded = false;
+               /* the class could not be loaded, free the classinfo struct */
+
+               class_free(c);
+
+       } else {
+               /* Store this class in the loaded class cache this step also
+               checks the loading constraints. If the class has been loaded
+               before, the earlier loaded class is returned. */
 
-               /* now free the allocated memory, otherwise we could ran into a DOS */
-               class_remove(c);
+               classinfo *res = classcache_store(NULL, c, true);
+
+               if (!res) {
+                       /* exception */
+                       class_free(c);
+               }
+
+               r = res;
+       }
+
+       /* SUN compatible -verbose:class output */
+
+       if (opt_verboseclass && r) {
+               printf("[Loaded ");
+               utf_display_classname(name);
+               printf(" from %s]\n", cb->path);
        }
 
        /* free memory */
+
        suck_stop(cb);
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        /* measure time */
 
        if (getloadingtime)
@@ -1937,12 +1721,6 @@ classinfo *load_class_bootstrap(classinfo *c)
                compilingtime_start();
 #endif
 
-#if defined(USE_THREADS)
-       /* leave the monitor */
-
-       builtin_monitorexit((java_objectheader *) c);
-#endif
-
        return r;
 }
 
@@ -1958,55 +1736,67 @@ classinfo *load_class_bootstrap(classinfo *c)
    The loaded class is removed from the list 'unloadedclasses' and
    added to the list 'unlinkedclasses'.
        
+   SYNCHRONIZATION:
+       This function is NOT synchronized!
+   
 *******************************************************************************/
 
 classinfo *load_class_from_classbuffer(classbuffer *cb)
 {
        classinfo *c;
-       classinfo *tc;
-       u4 i;
+       utf *name;
+       utf *supername;
+       u4 i,j;
        u4 ma, mi;
        s4 dumpsize;
        descriptor_pool *descpool;
-       char msg[MAXLOGTEXT];               /* maybe we get an exception */
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        u4 classrefsize;
        u4 descsize;
 #endif
 
        /* get the classbuffer's class */
+
        c = cb->class;
 
-       /* maybe the class is already loaded */
-       if (c->loaded)
+       /* the class is already loaded */
+
+       if (c->state & CLASS_LOADED)
                return c;
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
                count_class_loads++;
 #endif
 
+#if !defined(NDEBUG)
        /* output for debugging purposes */
+
        if (loadverbose)
                log_message_class("Loading class: ", c);
+#endif
        
        /* mark start of dump memory area */
+
        dumpsize = dump_size();
 
-       /* class is somewhat loaded */
-       c->loaded = true;
+       /* class is currently loading */
 
-       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+       c->state |= CLASS_LOADING;
+
+       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
                goto return_exception;
 
        /* check signature */
+
        if (suck_u4(cb) != MAGIC) {
-               *exceptionptr = new_classformaterror(c, "Bad magic number");
+               exceptions_throw_classformaterror(c, "Bad magic number");
 
                goto return_exception;
        }
 
        /* check version */
+
        mi = suck_u2(cb);
        ma = suck_u2(cb);
 
@@ -2020,41 +1810,38 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        /* create a new descriptor pool */
+
        descpool = descriptor_pool_new(c);
-       
+
        /* load the constant pool */
-       if (!load_constantpool(cb,descpool))
+
+       if (!load_constantpool(cb, descpool))
                goto return_exception;
 
-       /*JOWENN*/
-       c->erroneous_state = 0;
-       c->initializing_thread = 0;     
-       /*JOWENN*/
        c->classUsed = NOTUSED; /* not used initially CO-RT */
        c->impldBy = NULL;
 
        /* ACC flags */
-       if (!check_classbuffer_size(cb, 2))
+
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->flags = suck_u2(cb);
-       /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
 
        /* check ACC flags consistency */
+
        if (c->flags & ACC_INTERFACE) {
                if (!(c->flags & ACC_ABSTRACT)) {
                        /* We work around this because interfaces in JDK 1.1 are
                         * not declared abstract. */
 
                        c->flags |= ACC_ABSTRACT;
-                       /* panic("Interface class not declared abstract"); */
                }
 
                if (c->flags & ACC_FINAL) {
-                       *exceptionptr =
-                               new_classformaterror(c,
-                                                                        "Illegal class modifiers: 0x%X", c->flags);
-
+                       exceptions_throw_classformaterror(c,
+                                                                                         "Illegal class modifiers: 0x%X",
+                                                                                         c->flags);
                        goto return_exception;
                }
 
@@ -2064,38 +1851,57 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
-               *exceptionptr =
-                       new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
-
+               exceptions_throw_classformaterror(c,
+                                                                                 "Illegal class modifiers: 0x%X",
+                                                                                 c->flags);
                goto return_exception;
        }
 
-       if (!check_classbuffer_size(cb, 2 + 2))
+       if (!suck_check_classbuffer_size(cb, 2 + 2))
                goto return_exception;
 
        /* this class */
+
        i = suck_u2(cb);
-       if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
+       if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
                goto return_exception;
 
-       if (tc != c) {
+       if (c->name == utf_not_named_yet) {
+               /* we finally have a name for this class */
+               c->name = name;
+               class_set_packagename(c);
+
+       } else if (name != c->name) {
+               char *msg;
+               s4    msglen;
+
+               msglen = utf_strlen(c->name) + strlen(" (wrong name: ") +
+                       utf_strlen(name) + strlen(")") + strlen("0");
+
+               msg = MNEW(char, msglen);
+
                utf_sprint(msg, c->name);
-               sprintf(msg + strlen(msg), " (wrong name: ");
-               utf_sprint(msg + strlen(msg), tc->name);
-               sprintf(msg + strlen(msg), ")");
+               strcat(msg, " (wrong name: ");
+               utf_strcat(msg, name);
+               strcat(msg, ")");
 
                *exceptionptr =
                        new_exception_message(string_java_lang_NoClassDefFoundError, msg);
 
+               MFREE(msg, char, msglen);
+
                goto return_exception;
        }
        
        /* retrieve superclass */
+
+       c->super.any = NULL;
        if ((i = suck_u2(cb))) {
-               if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
+               if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
                        goto return_exception;
 
                /* java.lang.Object may not have a super class. */
+
                if (c->name == utf_java_lang_Object) {
                        *exceptionptr =
                                new_exception_message(string_java_lang_ClassFormatError,
@@ -2105,8 +1911,9 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                }
 
                /* Interfaces must have java.lang.Object as super class. */
+
                if ((c->flags & ACC_INTERFACE) &&
-                       c->super->name != utf_java_lang_Object) {
+                       supername != utf_java_lang_Object) {
                        *exceptionptr =
                                new_exception_message(string_java_lang_ClassFormatError,
                                                                          "Interfaces must have java.lang.Object as superclass");
@@ -2115,37 +1922,39 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                }
 
        } else {
-               c->super = NULL;
+               supername = NULL;
 
                /* This is only allowed for java.lang.Object. */
-               if (c->name != utf_java_lang_Object) {
-                       *exceptionptr = new_classformaterror(c, "Bad superclass index");
 
+               if (c->name != utf_java_lang_Object) {
+                       exceptions_throw_classformaterror(c, "Bad superclass index");
                        goto return_exception;
                }
        }
                         
        /* retrieve interfaces */
-       if (!check_classbuffer_size(cb, 2))
+
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->interfacescount = suck_u2(cb);
 
-       if (!check_classbuffer_size(cb, 2 * c->interfacescount))
+       if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
                goto return_exception;
 
-       c->interfaces = MNEW(classinfo*, c->interfacescount);
+       c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
        for (i = 0; i < c->interfacescount; i++) {
-               if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+               /* the classrefs are created later */
+               if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
                        goto return_exception;
        }
 
        /* load fields */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->fieldscount = suck_u2(cb);
-       c->fields = GCNEW(fieldinfo, c->fieldscount);
+       c->fields = GCNEW_UNCOLLECTABLE(fieldinfo, c->fieldscount);
 /*     c->fields = MNEW(fieldinfo, c->fieldscount); */
        for (i = 0; i < c->fieldscount; i++) {
                if (!load_field(cb, &(c->fields[i]),descpool))
@@ -2153,7 +1962,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        /* load methods */
-       if (!check_classbuffer_size(cb, 2))
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        c->methodscount = suck_u2(cb);
@@ -2165,60 +1974,133 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        }
 
        /* create the class reference table */
-       c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
+
+       c->classrefs =
+               descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
 
        /* allocate space for the parsed descriptors */
+
        descriptor_pool_alloc_parsed_descriptors(descpool);
-       c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
+       c->parseddescs =
+               descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat) {
-               descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
+               descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
                count_classref_len += classrefsize;
                count_parsed_desc_len += descsize;
        }
 #endif
 
-       /* parse the loaded descriptors */
-       for (i=0; i<c->cpcount; ++i) {
-               constant_FMIref *fmi;
-               
-               switch (c->cptags[i]) {
-                       case CONSTANT_Class:
-                               /* XXX set classref */
-                               break;
-                       case CONSTANT_Fieldref:
-                               fmi = (constant_FMIref *)c->cpinfos[i];
-                               fmi->parseddesc.fd = 
-                                       descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
-                               if (!fmi->parseddesc.fd)
-                                       goto return_exception;
-                               fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
-                               break;
-                       case CONSTANT_Methodref:
-                       case CONSTANT_InterfaceMethodref:
-                               fmi = (constant_FMIref *)c->cpinfos[i];
-                               fmi->parseddesc.md = 
-                                       descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
-                               if (!fmi->parseddesc.md)
-                                       goto return_exception;
-                               fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
-                               break;
+       /* put the classrefs in the constant pool */
+       for (i = 0; i < c->cpcount; i++) {
+               if (c->cptags[i] == CONSTANT_Class) {
+                       utf *name = (utf *) c->cpinfos[i];
+                       c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
                }
        }
+
+       /* set the super class reference */
+
+       if (supername) {
+               c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
+               if (!c->super.ref)
+                       goto return_exception;
+       }
+
+       /* set the super interfaces references */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               c->interfaces[i].ref =
+                       descriptor_pool_lookup_classref(descpool,
+                                                                                       (utf *) c->interfaces[i].any);
+               if (!c->interfaces[i].ref)
+                       goto return_exception;
+       }
+
+       /* parse field descriptors */
+
        for (i = 0; i < c->fieldscount; i++) {
-               c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
+               c->fields[i].parseddesc =
+                       descriptor_pool_parse_field_descriptor(descpool,
+                                                                                                  c->fields[i].descriptor);
                if (!c->fields[i].parseddesc)
                        goto return_exception;
        }
+
+       /* parse method descriptors */
+
        for (i = 0; i < c->methodscount; i++) {
-               c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor);
-               if (!c->methods[i].parseddesc)
+               methodinfo *m = &c->methods[i];
+               m->parseddesc =
+                       descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
+                                                                                                       m->flags, class_get_self_classref(m->class));
+               if (!m->parseddesc)
                        goto return_exception;
+
+               for (j = 0; j < m->exceptiontablelength; j++) {
+                       if (!m->exceptiontable[j].catchtype.any)
+                               continue;
+                       if ((m->exceptiontable[j].catchtype.ref =
+                                descriptor_pool_lookup_classref(descpool,
+                                               (utf *) m->exceptiontable[j].catchtype.any)) == NULL)
+                               goto return_exception;
+               }
+
+               for (j = 0; j < m->thrownexceptionscount; j++) {
+                       if (!m->thrownexceptions[j].any)
+                               continue;
+                       if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
+                                               (utf *) m->thrownexceptions[j].any)) == NULL)
+                               goto return_exception;
+               }
+       }
+
+       /* parse the loaded descriptors */
+
+       for (i = 0; i < c->cpcount; i++) {
+               constant_FMIref *fmi;
+               s4               index;
+               
+               switch (c->cptags[i]) {
+               case CONSTANT_Fieldref:
+                       fmi = (constant_FMIref *) c->cpinfos[i];
+                       fmi->parseddesc.fd =
+                               descriptor_pool_parse_field_descriptor(descpool,
+                                                                                                          fmi->descriptor);
+                       if (!fmi->parseddesc.fd)
+                               goto return_exception;
+                       index = (int) (size_t) fmi->classref;
+                       fmi->classref =
+                               (constant_classref *) class_getconstant(c, index,
+                                                                                                               CONSTANT_Class);
+                       if (!fmi->classref)
+                               goto return_exception;
+                       break;
+               case CONSTANT_Methodref:
+               case CONSTANT_InterfaceMethodref:
+                       fmi = (constant_FMIref *) c->cpinfos[i];
+                       index = (int) (size_t) fmi->classref;
+                       fmi->classref =
+                               (constant_classref *) class_getconstant(c, index,
+                                                                                                               CONSTANT_Class);
+                       if (!fmi->classref)
+                               goto return_exception;
+                       fmi->parseddesc.md =
+                               descriptor_pool_parse_method_descriptor(descpool,
+                                                                                                               fmi->descriptor,
+                                                                                                               ACC_UNDEF,
+                                                                                                               fmi->classref);
+                       if (!fmi->parseddesc.md)
+                               goto return_exception;
+                       break;
+               }
        }
 
+#ifdef ENABLE_VERIFIER
        /* Check if all fields and methods can be uniquely
         * identified by (name,descriptor). */
+
        if (opt_verify) {
                /* We use a hash table here to avoid making the
                 * average case quadratic in # of methods, fields.
@@ -2263,10 +2145,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                do {
                                        if (c->fields[old].name == fi->name &&
                                                c->fields[old].descriptor == fi->descriptor) {
-                                               *exceptionptr =
-                                                       new_classformaterror(c,
-                                                                                                "Repetitive field name/signature");
-
+                                               exceptions_throw_classformaterror(c, "Repetitive field name/signature");
                                                goto return_exception;
                                        }
                                } while ((old = next[old]));
@@ -2297,10 +2176,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                do {
                                        if (c->methods[old].name == mi->name &&
                                                c->methods[old].descriptor == mi->descriptor) {
-                                               *exceptionptr =
-                                                       new_classformaterror(c,
-                                                                                                "Repetitive method name/signature");
-
+                                               exceptions_throw_classformaterror(c, "Repetitive method name/signature");
                                                goto return_exception;
                                        }
                                } while ((old = next[old]));
@@ -2310,17 +2186,19 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                
                MFREE(hashtab, u2, (hashlen + len));
        }
+#endif /* ENABLE_VERIFIER */
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat) {
                count_class_infos += sizeof(classinfo*) * c->interfacescount;
-               count_class_infos += sizeof(fieldinfo) * c->fieldscount;
+               count_class_infos += sizeof(fieldinfo)  * c->fieldscount;
                count_class_infos += sizeof(methodinfo) * c->methodscount;
        }
 #endif
 
        /* load attribute structures */
-       if (!check_classbuffer_size(cb, 2))
+
+       if (!suck_check_classbuffer_size(cb, 2))
                goto return_exception;
 
        if (!load_attributes(cb, suck_u2(cb)))
@@ -2333,980 +2211,239 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
         */
        if ((ma == 45 && mi > 3) || ma > 45) {
                /* check if all data has been read */
-               s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
+               s4 classdata_left = ((cb->data + cb->size) - cb->pos);
 
                if (classdata_left > 0) {
-                       *exceptionptr =
-                               new_classformaterror(c, "Extra bytes at the end of class file");
+                       exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
                        goto return_exception;
                }
        }
 #endif
 
        /* release dump area */
+
        dump_release(dumpsize);
-       
+
+       /* revert loading state and class is loaded */
+
+       c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+
+#if !defined(NDEBUG)
        if (loadverbose)
                log_message_class("Loading done class: ", c);
+#endif
 
        return c;
 
 return_exception:
        /* release dump area */
+
        dump_release(dumpsize);
 
        /* an exception has been thrown */
+
        return NULL;
 }
 
 
+/* load_newly_created_array ****************************************************
+
+   Load a newly created array class.
 
-/******************* Function: class_new_array *********************************
+       RETURN VALUE:
+           c....................the array class C has been loaded
+               other classinfo......the array class was found in the class cache, 
+                                    C has been freed
+           NULL.................an exception has been thrown
 
-    This function is called by class_new to setup an array class.
+       Note:
+               This is an internal function. Do not use it unless you know exactly
+               what you are doing!
+
+               Use one of the load_class_... functions for general array class loading.
 
 *******************************************************************************/
 
-void class_new_array(classinfo *c)
+classinfo *load_newly_created_array(classinfo *c, java_objectheader *loader)
 {
-       classinfo *comp = NULL;
-       methodinfo *clone;
-       methoddesc *clonedesc;
+       classinfo         *comp = NULL;
+       methodinfo        *clone;
+       methoddesc        *clonedesc;
        constant_classref *classrefs;
-       int namelen;
+       char              *text;
+       s4                 namelen;
+       utf               *u;
 
-       /* Check array class name */
+       text = c->name->text;
        namelen = c->name->blength;
-       if (namelen < 2 || c->name->text[0] != '[')
-               panic("Invalid array class name");
 
-       /* Check the component type */
-       switch (c->name->text[1]) {
+       /* Check array class name */
+
+       if (namelen < 2 || text[0] != '[') {
+               *exceptionptr = new_noclassdeffounderror(c->name);
+               return NULL;
+       }
+
+       /* Check the element type */
+
+       switch (text[1]) {
        case '[':
                /* c is an array of arrays. We have to create the component class. */
-               if (opt_eager) {
-                       comp = class_new_intern(utf_new_intern(c->name->text + 1,
-                                                                                                  namelen - 1));
-                       load_class_from_classloader(comp, c->classloader);
-                       list_addfirst(&unlinkedclasses, comp);
 
-               } else {
-                       comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
-               }
+               u = utf_new(text + 1, namelen - 1);
+               if (!(comp = load_class_from_classloader(u, loader)))
+                       return NULL;
+
+               LOADER_ASSERT(comp->state & CLASS_LOADED);
+
+               if (opt_eager)
+                       if (!link_class(c))
+                               return NULL;
+
+               /* the array's flags are that of the component class */
+               c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = comp->classloader;
                break;
 
        case 'L':
                /* c is an array of objects. */
-               if (namelen < 4 || c->name->text[namelen - 1] != ';')
-                       panic("Invalid array class name");
-
-               if (opt_eager) {
-                       comp = class_new_intern(utf_new_intern(c->name->text + 2,
-                                                                                                  namelen - 3));
-                       load_class_from_classloader(comp, c->classloader);
-                       list_addfirst(&unlinkedclasses, comp);
 
-               } else {
-                       comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
+               /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+               if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+                       *exceptionptr = new_noclassdeffounderror(c->name);
+                       return NULL;
                }
-               break;
-       }
 
-       /* Setup the array class */
-       c->super = class_java_lang_Object;
-       c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+               u = utf_new(text + 2, namelen - 3);
 
-    c->interfacescount = 2;
-    c->interfaces = MNEW(classinfo*, 2);
+               if (!(comp = load_class_from_classloader(u, loader)))
+                       return NULL;
 
-       if (opt_eager) {
-               classinfo *tc;
+               LOADER_ASSERT(comp->state & CLASS_LOADED);
 
-               tc = class_java_lang_Cloneable;
-               load_class_bootstrap(tc);
-               list_addfirst(&unlinkedclasses, tc);
-               c->interfaces[0] = tc;
+               if (opt_eager)
+                       if (!link_class(c))
+                               return NULL;
 
-               tc = class_java_io_Serializable;
-               load_class_bootstrap(tc);
-               list_addfirst(&unlinkedclasses, tc);
-               c->interfaces[1] = tc;
-
-       } else {
-               c->interfaces[0] = class_java_lang_Cloneable;
-               c->interfaces[1] = class_java_io_Serializable;
-       }
-
-       c->methodscount = 1;
-       c->methods = MNEW(methodinfo, c->methodscount);
-
-       classrefs = MNEW(constant_classref,1);
-       CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
-
-       clonedesc = NEW(methoddesc);
-       clonedesc->returntype.type = TYPE_ADDRESS;
-       clonedesc->returntype.classref = classrefs;
-       clonedesc->returntype.arraydim = 0;
-       clonedesc->paramcount = 0;
-       clonedesc->paramslots = 0;
-
-       clone = c->methods;
-       MSET(clone, 0, methodinfo, 1);
-       clone->flags = ACC_PUBLIC;
-       clone->name = utf_new_char("clone");
-       clone->descriptor = utf_void__java_lang_Object;
-       clone->parseddesc = clonedesc;
-       clone->class = c;
-       clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
-       clone->monoPoly = MONO;
-
-       /* XXX: field: length? */
-
-       /* array classes are not loaded from class files */
-       c->loaded = true;
-       c->parseddescs = (u1*) clonedesc;
-       c->parseddescsize = sizeof(methodinfo);
-       c->classrefs = classrefs;
-       c->classrefcount = 1;
-
-       /* XXX insert class into the loaded class cache */
-}
-
-
-/************************* Function: class_findfield ***************************
-       
-       Searches a 'classinfo' structure for a field having the given name and
-       type.
-
-*******************************************************************************/
-
-fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
-
-       for (i = 0; i < c->fieldscount; i++) { 
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
-                       return &(c->fields[i]);                                                         
-    }
-
-       panic("Can not find field given in CONSTANT_Fieldref");
-
-       /* keep compiler happy */
-       return NULL;
-}
-
-
-/****************** Function: class_resolvefield_int ***************************
-
-    This is an internally used helper function. Do not use this directly.
-
-       Tries to resolve a field having the given name and type.
-    If the field cannot be resolved, NULL is returned.
-
-*******************************************************************************/
-
-static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
-{
-       fieldinfo *fi;
-       s4         i;
-
-       /* search for field in class c */
-
-       for (i = 0; i < c->fieldscount; i++) { 
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
-                       return &(c->fields[i]);
-               }
-    }
-
-       /* try superinterfaces recursively */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               fi = class_resolvefield_int(c->interfaces[i], name, desc);
-               if (fi)
-                       return fi;
-       }
-
-       /* try superclass */
-
-       if (c->super)
-               return class_resolvefield_int(c->super, name, desc);
-
-       /* not found */
-
-       return NULL;
-}
-
-
-/********************* Function: class_resolvefield ***************************
-       
-       Resolves a reference from REFERER to a field with NAME and DESC in class C.
-
-    If the field cannot be resolved the return value is NULL. If EXCEPT is
-    true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
-                                                         classinfo *referer, bool except)
-{
-       fieldinfo *fi;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-       fi = class_resolvefield_int(c, name, desc);
-
-       if (!fi) {
-               if (except)
-                       *exceptionptr =
-                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
-                                                                                name);
-
-               return NULL;
-       }
-
-       /* XXX check access rights */
-
-       return fi;
-}
-
-
-/* class_findmethod ************************************************************
-       
-   Searches a 'classinfo' structure for a method having the given name
-   and descriptor. If descriptor is NULL, it is ignored.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *m;
-       s4 i;
-
-       for (i = 0; i < c->methodscount; i++) {
-               m = &(c->methods[i]);
-
-               if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
-                       return m;
-       }
-
-       return NULL;
-}
-
-
-/*********************** Function: class_fetchmethod **************************
-       
-    like class_findmethod, but aborts with an error if the method is not found
-
-*******************************************************************************/
-
-methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *mi;
-
-       mi = class_findmethod(c, name, desc);
-
-       if (!mi) {
-               log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
-               log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
-               log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
-               panic("Method not found");
-       }
-
-       return mi;
-}
-
-
-/************************* Function: class_findmethod_approx ******************
-       
-       like class_findmethod but ignores the return value when comparing the
-       descriptor.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
-
-       for (i = 0; i < c->methodscount; i++) {
-               if (c->methods[i].name == name) {
-                       utf *meth_descr = c->methods[i].descriptor;
-                       
-                       if (desc == NULL) 
-                               /* ignore type */
-                               return &(c->methods[i]);
-
-                       if (desc->blength <= meth_descr->blength) {
-                               /* current position in utf text   */
-                               char *desc_utf_ptr = desc->text;      
-                               char *meth_utf_ptr = meth_descr->text;                                    
-                               /* points behind utf strings */
-                               char *desc_end = utf_end(desc);         
-                               char *meth_end = utf_end(meth_descr);   
-                               char ch;
-
-                               /* compare argument types */
-                               while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
-
-                                       if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
-                                               break; /* no match */
-
-                                       if (ch == ')')
-                                               return &(c->methods[i]);   /* all parameter types equal */
-                               }
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-
-/***************** Function: class_resolvemethod_approx ***********************
-       
-       Searches a class and every super class for a method (without paying
-       attention to the return value)
-
-*******************************************************************************/
-
-methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
-{
-       while (c) {
-               /* search for method (ignore returntype) */
-               methodinfo *m = class_findmethod_approx(c, name, desc);
-               /* method found */
-               if (m) return m;
-               /* search superclass */
-               c = c->super;
-       }
-
-       return NULL;
-}
-
-
-/* class_resolvemethod *********************************************************
-       
-   Searches a class and it's super classes for a method.
-
-*******************************************************************************/
-
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
-{
-       methodinfo *m;
-
-       while (c) {
-               m = class_findmethod(c, name, desc);
-
-               if (m)
-                       return m;
-
-               c = c->super;
-       }
-
-       return NULL;
-}
-
-
-/* class_resolveinterfacemethod_intern *****************************************
-
-   Internally used helper function. Do not use this directly.
-
-*******************************************************************************/
-
-static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
-                                                                                                          utf *name, utf *desc)
-{
-       methodinfo *m;
-       s4 i;
-       
-       m = class_findmethod(c, name, desc);
-
-       if (m)
-               return m;
-
-       /* try the superinterfaces */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
-
-               if (m)
-                       return m;
-       }
-       
-       return NULL;
-}
-
-/* class_resolveinterfacemethod ************************************************
-
-   Resolves a reference from REFERER to a method with NAME and DESC in
-   interface C.
-
-   If the method cannot be resolved the return value is NULL. If
-   EXCEPT is true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
-                                                                                classinfo *referer, bool except)
-{
-       methodinfo *mi;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-       if (!(c->flags & ACC_INTERFACE)) {
-               if (except)
-                       *exceptionptr =
-                               new_exception(string_java_lang_IncompatibleClassChangeError);
-
-               return NULL;
-       }
-
-       mi = class_resolveinterfacemethod_intern(c, name, desc);
-
-       if (mi)
-               return mi;
-
-       /* try class java.lang.Object */
-       mi = class_findmethod(class_java_lang_Object, name, desc);
-
-       if (mi)
-               return mi;
-
-       if (except)
-               *exceptionptr =
-                       new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
-
-       return NULL;
-}
-
-
-/* class_resolveclassmethod ****************************************************
-       
-    Resolves a reference from REFERER to a method with NAME and DESC in
-    class C.
-
-    If the method cannot be resolved the return value is NULL. If EXCEPT is
-    true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
-                                                                        classinfo *referer, bool except)
-{
-       classinfo  *cls;
-       methodinfo *mi;
-       s4          i;
-       char       *msg;
-       s4          msglen;
-
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
-/*     if (c->flags & ACC_INTERFACE) { */
-/*             if (except) */
-/*                     *exceptionptr = */
-/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
-/*             return NULL; */
-/*     } */
-
-       /* try class c and its superclasses */
-
-       cls = c;
-
-       while (cls) {
-               mi = class_findmethod(cls, name, desc);
-
-               if (mi)
-                       goto found;
-
-               cls = cls->super;
-       }
-
-       /* try the superinterfaces */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
-
-               if (mi)
-                       goto found;
-       }
-       
-       if (except) {
-               msglen = utf_strlen(c->name) + strlen(".") + utf_strlen(name) +
-                       utf_strlen(desc) + strlen("0");
-
-               msg = MNEW(char, msglen);
-
-               utf_sprint(msg, c->name);
-               strcat(msg, ".");
-               utf_sprint(msg + strlen(msg), name);
-               utf_sprint(msg + strlen(msg), desc);
-
-               *exceptionptr =
-                       new_exception_message(string_java_lang_NoSuchMethodError, msg);
-
-               MFREE(msg, char, msglen);
-       }
-
-       return NULL;
-
- found:
-       if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
-               if (except)
-                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
-
-               return NULL;
-       }
-
-       /* XXX check access rights */
-
-       return mi;
-}
-
-
-/************************* Function: class_issubclass **************************
-
-       Checks if sub is a descendant of super.
-       
-*******************************************************************************/
-
-bool class_issubclass(classinfo *sub, classinfo *super)
-{
-       for (;;) {
-               if (!sub) return false;
-               if (sub == super) return true;
-               sub = sub->super;
-       }
-}
-
-
-/****************** Initialization function for classes ******************
-
-       In Java, every class can have a static initialization function. This
-       function has to be called BEFORE calling other methods or accessing static
-       variables.
-
-*******************************************************************************/
-
-static classinfo *class_init_intern(classinfo *c);
-
-classinfo *class_init(classinfo *c)
-{
-       classinfo *r;
-
-       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;
-       }
-
-       /* this initalizing run begins NOW */
-       c->initializing = true;
-
-       /* call the internal function */
-       r = class_init_intern(c);
-
-       /* if return value is not NULL everything was ok and the class is
-          initialized */
-       if (r)
-               c->initialized = true;
-
-       /* this initalizing run is done */
-       c->initializing = false;
-
-#if defined(USE_THREADS)
-       /* leave the monitor */
-
-       builtin_monitorexit((java_objectheader *) c);
-#endif
-
-       return r;
-}
-
-
-/* this function MUST NOT be called directly, because of thread <clinit>
-   race conditions */
+               /* the array's flags are that of the component class */
+               c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = comp->classloader;
+               break;
 
-static classinfo *class_init_intern(classinfo *c)
-{
-       methodinfo *m;
-       s4 i;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       int b;
-#endif
+       default:
+               /* c is an array of a primitive type */
 
-       /* maybe the class is not already loaded */
-       if (!c->loaded)
-               if (!load_class_bootstrap(c))
+               /* check for cases like `[II' */
+               if (namelen > 2) {
+                       *exceptionptr = new_noclassdeffounderror(c->name);
                        return NULL;
-
-       /* maybe the class is not already linked */
-       if (!c->linked)
-               if (!link_class(c))
-                       return NULL;
-
-#if defined(STATISTICS)
-       if (opt_stat)
-               count_class_inits++;
-#endif
-
-       /* initialize super class */
-
-       if (c->super) {
-               if (!c->super->initialized) {
-                       if (initverbose) {
-                               char logtext[MAXLOGTEXT];
-                               sprintf(logtext, "Initialize super class ");
-                               utf_sprint_classname(logtext + strlen(logtext), c->super->name);
-                               sprintf(logtext + strlen(logtext), " from ");
-                               utf_sprint_classname(logtext + strlen(logtext), c->name);
-                               log_text(logtext);
-                       }
-
-                       if (!class_init(c->super))
-                               return NULL;
                }
-       }
 
-       /* initialize interface classes */
-
-       for (i = 0; i < c->interfacescount; i++) {
-               if (!c->interfaces[i]->initialized) {
-                       if (initverbose) {
-                               char logtext[MAXLOGTEXT];
-                               sprintf(logtext, "Initialize interface class ");
-                               utf_sprint_classname(logtext + strlen(logtext), c->interfaces[i]->name);
-                               sprintf(logtext + strlen(logtext), " from ");
-                               utf_sprint_classname(logtext + strlen(logtext), c->name);
-                               log_text(logtext);
-                       }
-                       
-                       if (!class_init(c->interfaces[i]))
-                               return NULL;
-               }
+               /* the accessibility of the array class is public (VM Spec 5.3.3) */
+               c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+               c->classloader = NULL;
        }
 
-       m = class_findmethod(c, utf_clinit, utf_void__void);
-
-       if (!m) {
-               if (initverbose) {
-                       char logtext[MAXLOGTEXT];
-                       sprintf(logtext, "Class ");
-                       utf_sprint_classname(logtext + strlen(logtext), c->name);
-                       sprintf(logtext + strlen(logtext), " has no static class initializer");
-                       log_text(logtext);
-               }
-
-               return c;
-       }
-
-       /* Sun's and IBM's JVM don't care about the static flag */
-/*     if (!(m->flags & ACC_STATIC)) { */
-/*             panic("Class initializer is not static!"); */
-
-       if (initverbose)
-               log_message_class("Starting static class initializer for class: ", c);
+       LOADER_ASSERT(class_java_lang_Object);
+       LOADER_ASSERT(class_java_lang_Cloneable);
+       LOADER_ASSERT(class_java_io_Serializable);
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       b = blockInts;
-       blockInts = 0;
-#endif
-
-       /* now call the initializer */
-       asm_calljavafunction(m, NULL, NULL, NULL, NULL);
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       assert(blockInts == 0);
-       blockInts = b;
-#endif
-
-       /* we have an exception or error */
-       if (*exceptionptr) {
-               /* class is NOT initialized */
-               c->initialized = false;
-
-               /* is this an exception, than wrap it */
-               if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
-                       java_objectheader *xptr;
-                       java_objectheader *cause;
-
-                       /* get the cause */
-                       cause = *exceptionptr;
-
-                       /* clear exception, because we are calling jit code again */
-                       *exceptionptr = NULL;
-
-                       /* wrap the exception */
-                       xptr =
-                               new_exception_throwable(string_java_lang_ExceptionInInitializerError,
-                                                                               (java_lang_Throwable *) cause);
-
-                       /* XXX should we exit here? */
-                       if (*exceptionptr)
-                               throw_exception();
-
-                       /* set new exception */
-                       *exceptionptr = xptr;
-               }
+       /* setup the array class */
 
-               return NULL;
-       }
+       c->super.cls = class_java_lang_Object;
 
-       if (initverbose)
-               log_message_class("Finished static class initializer for class: ", c);
+    c->interfacescount = 2;
+    c->interfaces = MNEW(classref_or_classinfo, 2);
 
-       return c;
-}
+       if (opt_eager) {
+               classinfo *tc;
 
+               tc = class_java_lang_Cloneable;
+               LOADER_ASSERT(tc->state & CLASS_LOADED);
+               list_addfirst(&unlinkedclasses, tc);
+               c->interfaces[0].cls = tc;
 
-void class_showconstanti(classinfo *c, int ii) 
-{
-       u4 i = ii;
-       voidptr e;
-               
-       e = c->cpinfos [i];
-       printf ("#%d:  ", (int) i);
-       if (e) {
-               switch (c->cptags [i]) {
-               case CONSTANT_Class:
-                       printf("Classreference -> ");
-                       utf_display(((classinfo*)e)->name);
-                       break;
-                               
-               case CONSTANT_Fieldref:
-                       printf("Fieldref -> "); goto displayFMIi;
-               case CONSTANT_Methodref:
-                       printf("Methodref -> "); goto displayFMIi;
-               case CONSTANT_InterfaceMethodref:
-                       printf("InterfaceMethod -> "); goto displayFMIi;
-               displayFMIi:
-                       {
-                               constant_FMIref *fmi = e;
-                               utf_display(fmi->class->name);
-                               printf(".");
-                               utf_display(fmi->name);
-                               printf(" ");
-                               utf_display(fmi->descriptor);
-                       }
-                       break;
+               tc = class_java_io_Serializable;
+               LOADER_ASSERT(tc->state & CLASS_LOADED);
+               list_addfirst(&unlinkedclasses, tc);
+               c->interfaces[1].cls = tc;
 
-               case CONSTANT_String:
-                       printf("String -> ");
-                       utf_display(e);
-                       break;
-               case CONSTANT_Integer:
-                       printf("Integer -> %d", (int) (((constant_integer*)e)->value));
-                       break;
-               case CONSTANT_Float:
-                       printf("Float -> %f", ((constant_float*)e)->value);
-                       break;
-               case CONSTANT_Double:
-                       printf("Double -> %f", ((constant_double*)e)->value);
-                       break;
-               case CONSTANT_Long:
-                       {
-                               u8 v = ((constant_long*)e)->value;
-#if U8_AVAILABLE
-                               printf("Long -> %ld", (long int) v);
-#else
-                               printf("Long -> HI: %ld, LO: %ld\n", 
-                                           (long int) v.high, (long int) v.low);
-#endif 
-                       }
-                       break;
-               case CONSTANT_NameAndType:
-                       { 
-                               constant_nameandtype *cnt = e;
-                               printf("NameAndType: ");
-                               utf_display(cnt->name);
-                               printf(" ");
-                               utf_display(cnt->descriptor);
-                       }
-                       break;
-               case CONSTANT_Utf8:
-                       printf("Utf8 -> ");
-                       utf_display(e);
-                       break;
-               default: 
-                       panic("Invalid type of ConstantPool-Entry");
-               }
+       } else {
+               c->interfaces[0].cls = class_java_lang_Cloneable;
+               c->interfaces[1].cls = class_java_io_Serializable;
        }
-       printf("\n");
-}
 
+       c->methodscount = 1;
+       c->methods = MNEW(methodinfo, c->methodscount);
 
-void class_showconstantpool (classinfo *c) 
-{
-       u4 i;
-       voidptr e;
-
-       printf ("---- dump of constant pool ----\n");
+       classrefs = MNEW(constant_classref, 2);
+       CLASSREF_INIT(classrefs[0], c, c->name);
+       CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
 
-       for (i=0; i<c->cpcount; i++) {
-               printf ("#%d:  ", (int) i);
-               
-               e = c -> cpinfos [i];
-               if (e) {
-                       
-                       switch (c -> cptags [i]) {
-                       case CONSTANT_Class:
-                               printf ("Classreference -> ");
-                               utf_display ( ((classinfo*)e) -> name );
-                               break;
-                               
-                       case CONSTANT_Fieldref:
-                               printf ("Fieldref -> "); goto displayFMI;
-                       case CONSTANT_Methodref:
-                               printf ("Methodref -> "); goto displayFMI;
-                       case CONSTANT_InterfaceMethodref:
-                               printf ("InterfaceMethod -> "); goto displayFMI;
-                       displayFMI:
-                               {
-                                       constant_FMIref *fmi = e;
-                                       utf_display ( fmi->class->name );
-                                       printf (".");
-                                       utf_display ( fmi->name);
-                                       printf (" ");
-                                       utf_display ( fmi->descriptor );
-                               }
-                               break;
-
-                       case CONSTANT_String:
-                               printf ("String -> ");
-                               utf_display (e);
-                               break;
-                       case CONSTANT_Integer:
-                               printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
-                               break;
-                       case CONSTANT_Float:
-                               printf ("Float -> %f", ((constant_float*)e) -> value);
-                               break;
-                       case CONSTANT_Double:
-                               printf ("Double -> %f", ((constant_double*)e) -> value);
-                               break;
-                       case CONSTANT_Long:
-                               {
-                                       u8 v = ((constant_long*)e) -> value;
-#if U8_AVAILABLE
-                                       printf ("Long -> %ld", (long int) v);
-#else
-                                       printf ("Long -> HI: %ld, LO: %ld\n", 
-                                                       (long int) v.high, (long int) v.low);
-#endif 
-                               }
-                               break;
-                       case CONSTANT_NameAndType:
-                               {
-                                       constant_nameandtype *cnt = e;
-                                       printf ("NameAndType: ");
-                                       utf_display (cnt->name);
-                                       printf (" ");
-                                       utf_display (cnt->descriptor);
-                               }
-                               break;
-                       case CONSTANT_Utf8:
-                               printf ("Utf8 -> ");
-                               utf_display (e);
-                               break;
-                       default: 
-                               panic ("Invalid type of ConstantPool-Entry");
-                       }
-               }
+       /* create descriptor for clone method */
+       /* we need one paramslot which is reserved for the 'this' parameter */
+       clonedesc = NEW(methoddesc);
+       clonedesc->returntype.type = TYPE_ADDRESS;
+       clonedesc->returntype.classref = classrefs + 1;
+       clonedesc->returntype.arraydim = 0;
+       /* initialize params to "empty", add real params below in
+          descriptor_params_from_paramtypes */
+       clonedesc->paramcount = 0;
+       clonedesc->paramslots = 0;
+       clonedesc->paramtypes[0].classref = classrefs + 0;
 
-               printf ("\n");
-       }
-}
+       /* create methodinfo */
 
+       clone = c->methods;
+       MSET(clone, 0, methodinfo, 1);
 
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       initObjectLock(&clone->header);
+#endif
 
-/********** Function: class_showmethods   (debugging only) *************/
+       /* if you delete the ACC_NATIVE below, set clone->maxlocals=1 (interpreter 
+          related) */
+       clone->flags = ACC_PUBLIC | ACC_NATIVE;
+       clone->name = utf_clone;
+       clone->descriptor = utf_void__java_lang_Object;
+       clone->parseddesc = clonedesc;
+       clone->class = c;
+       clone->monoPoly = MONO;
 
-void class_showmethods (classinfo *c)
-{
-       s4 i;
-       
-       printf ("--------- Fields and Methods ----------------\n");
-       printf ("Flags: ");     printflags (c->flags);  printf ("\n");
+       /* parse the descriptor to get the register allocation */
 
-       printf ("This: "); utf_display (c->name); printf ("\n");
-       if (c->super) {
-               printf ("Super: "); utf_display (c->super->name); printf ("\n");
-               }
-       printf ("Index: %d\n", c->index);
-       
-       printf ("interfaces:\n");       
-       for (i=0; i < c-> interfacescount; i++) {
-               printf ("   ");
-               utf_display (c -> interfaces[i] -> name);
-               printf (" (%d)\n", c->interfaces[i] -> index);
-               }
+       if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
+               return false;
 
-       printf ("fields:\n");           
-       for (i=0; i < c -> fieldscount; i++) {
-               field_display (&(c -> fields[i]));
-               }
+       clone->entrypoint =
+               codegen_createnativestub((functionptr) &builtin_clone_array, clone);
 
-       printf ("methods:\n");
-       for (i=0; i < c -> methodscount; i++) {
-               methodinfo *m = &(c->methods[i]);
-               if ( !(m->flags & ACC_STATIC)) 
-                       printf ("vftblindex: %d   ", m->vftblindex);
+       /* XXX: field: length? */
 
-               method_display ( m );
+       /* array classes are not loaded from class files */
 
-               }
+       c->state |= CLASS_LOADED;
+       c->parseddescs = (u1 *) clonedesc;
+       c->parseddescsize = sizeof(methodinfo);
+       c->classrefs = classrefs;
+       c->classrefcount = 1;
 
-       printf ("Virtual function table:\n");
-       for (i=0; i<c->vftbl->vftbllength; i++) {
-               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
-               }
+       /* insert class into the loaded class cache */
+       /* XXX free classinfo if NULL returned? */
 
+       return classcache_store(loader, c, true);
 }
 
 
-/******************************************************************************/
-/******************* General functions for the class loader *******************/
-/******************************************************************************/
-
-/******************** Function: loader_close ***********************************
+/* loader_close ****************************************************************
 
-       Frees all resources
+   Frees all resources.
        
 *******************************************************************************/
 
-void loader_close()
+void loader_close(void)
 {
-       classinfo *c;
-       s4 slot;
-
-       for (slot = 0; slot < class_hash.size; slot++) {
-               c = class_hash.ptr[slot];
-
-               while (c) {
-                       class_free(c);
-                       c = c->hashlink;
-               }
-       }
+       /* empty */
 }