check against method descriptors used for fields and vice versa
[cacao.git] / src / vm / loader.c
index b9f09209c79f8570f20dad8f1aa30835686beb18..501b3f6a43ea99aa20d1f8ca9eebd4944937c8b5 100644 (file)
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 2137 2005-03-30 10:18:38Z twisti $
+   $Id: loader.c 3386 2005-10-07 14:02:52Z edwin $
 
 */
 
-
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include "vm/exceptions.h"
 #include "vm/builtin.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/classcache.h"
 
 #if defined(USE_ZLIB)
 # include "vm/unzip.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen.inc.h"
 
+/******************************************************************************/
+/* DEBUG HELPERS                                                              */
+/******************************************************************************/
+
+/*#define LOADER_VERBOSE*/
+
+#ifndef NDEBUG
+#define LOADER_DEBUG
+#endif
+
+#ifdef LOADER_DEBUG
+#define LOADER_ASSERT(cond)  assert(cond)
+#else
+#define LOADER_ASSERT(cond)
+#endif
 
 #undef JOWENN_DEBUG
 #undef JOWENN_DEBUG1
 #undef JOWENN_DEBUG2
 
+#ifdef LOADER_VERBOSE
+static int loader_recursion = 0;
+#define LOADER_INDENT(str)   do { int i; for(i=0;i<loader_recursion*4;++i) {str[i]=' ';} str[i]=0;} while (0)
+#define LOADER_INC()  loader_recursion++
+#define LOADER_DEC()  loader_recursion--
+#else
+#define LOADER_INC()
+#define LOADER_DEC()
+#endif
+
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
 classpath_info *classpath_entries = NULL;
 
 
-/******************* function: checkfielddescriptor ****************************
+/* loader_init *****************************************************************
 
-       checks whether a field-descriptor is valid and aborts otherwise
-       all referenced classes are inserted into the list of unloaded classes
-       
-*******************************************************************************/
+   Initializes all lists and loads all classes required for the system
+   or the compiler.
 
-static void checkfielddescriptor (char *utf_ptr, char *end_pos)
+*******************************************************************************/
+bool loader_init(u1 *stackbottom)
 {
-       class_from_descriptor(utf_ptr,end_pos,NULL,
-                                                 CLASSLOAD_NEW
-                                                 | CLASSLOAD_NULLPRIMITIVE
-                                                 | CLASSLOAD_NOVOID
-                                                 | CLASSLOAD_CHECKEND);
-       
-       /* XXX use the following if -noverify */
-#if 0
-       char *tstart;  /* pointer to start of classname */
-       char ch;
-       char *start = utf_ptr;
-
-       switch (*utf_ptr++) {
-         case 'B':
-         case 'C':
-         case 'I':
-         case 'S':
-         case 'Z':  
-         case 'J':  
-         case 'F':  
-         case 'D':
-                 /* primitive type */  
-                 break;
-                 
-         case '[':
-         case 'L':
-                 if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
-                         panic ("Ill formed descriptor");
-                 break;
-                 
-         default:   
-                 panic ("Ill formed descriptor");
-       }                       
-       
-       /* exceeding characters */              
-       if (utf_ptr!=end_pos) panic ("descriptor has exceeding chars");
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       classpath_info *cpi;
+
+       /* Initialize the monitor pointer for zip/jar file locking. */
+
+       for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
+               if (cpi->type == CLASSPATH_ARCHIVE)
+                       initObjectLock(&cpi->header);
+       }
 #endif
-}
 
+       /* load some important classes */
 
-/******************* function checkmethoddescriptor ****************************
+       if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
+               return false;
 
-    checks whether a method-descriptor is valid and aborts otherwise.
-    All referenced classes are inserted into the list of unloaded classes.
+       if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
+               return false;
 
-    The number of arguments is returned. A long or double argument is counted
-    as two arguments.
-       
-*******************************************************************************/
+       if (!(class_java_lang_Cloneable =
+                 load_class_bootstrap(utf_java_lang_Cloneable)))
+               return false;
 
-static int checkmethoddescriptor(classinfo *c, utf *descriptor)
-{
-       char *utf_ptr;                      /* current position in utf text       */
-       char *end_pos;                      /* points behind utf string           */
-       s4 argcount = 0;                    /* number of arguments                */
-
-       utf_ptr = descriptor->text;
-       end_pos = utf_end(descriptor);
-
-       /* method descriptor must start with parenthesis */
-       if (utf_ptr == end_pos || *utf_ptr++ != '(')
-               panic ("Missing '(' in method descriptor");
-
-    /* check arguments */
-    while (utf_ptr != end_pos && *utf_ptr != ')') {
-               /* We cannot count the this argument here because
-                * we don't know if the method is static. */
-               if (*utf_ptr == 'J' || *utf_ptr == 'D')
-                       argcount+=2;
-               else
-                       argcount++;
-               class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
-                                                         CLASSLOAD_NEW
-                                                         | CLASSLOAD_NULLPRIMITIVE
-                                                         | CLASSLOAD_NOVOID);
-       }
-
-       if (utf_ptr == end_pos)
-               panic("Missing ')' in method descriptor");
-
-    utf_ptr++; /* skip ')' */
-
-       class_from_descriptor(utf_ptr,
-                                                 end_pos,
-                                                 NULL,
-                                                 CLASSLOAD_NEW |
-                                                 CLASSLOAD_NULLPRIMITIVE |
-                                                 CLASSLOAD_CHECKEND);
-
-       if (argcount > 255) {
-               *exceptionptr =
-                       new_classformaterror(c, "Too many arguments in signature");
+       if (!(class_java_io_Serializable =
+                 load_class_bootstrap(utf_java_io_Serializable)))
+               return false;
 
-               return 0;
-       }
 
-       return argcount;
+       /* load classes for wrapping primitive types */
 
-       /* XXX use the following if -noverify */
-#if 0
-       /* check arguments */
-       while ((c = *utf_ptr++) != ')') {
-               start = utf_ptr-1;
-               
-               switch (c) {
-               case 'B':
-               case 'C':
-               case 'I':
-               case 'S':
-               case 'Z':  
-               case 'J':  
-               case 'F':  
-               case 'D':
-                       /* primitive type */  
-                       break;
+       if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
+               return false;
 
-               case '[':
-               case 'L':
-                       if (!class_from_descriptor(start,end_pos,&utf_ptr,CLASSLOAD_NEW))
-                               panic ("Ill formed method descriptor");
-                       break;
-                       
-               default:   
-                       panic ("Ill formed methodtype-descriptor");
-               }
-       }
+       if (!(class_java_lang_Boolean =
+                 load_class_bootstrap(utf_java_lang_Boolean)))
+               return false;
 
-       /* check returntype */
-       if (*utf_ptr=='V') {
-               /* returntype void */
-               if ((utf_ptr+1) != end_pos) panic ("Method-descriptor has exceeding chars");
-       }
-       else
-               /* treat as field-descriptor */
-               checkfielddescriptor (utf_ptr,end_pos);
-#endif
-}
+       if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
+               return false;
 
+       if (!(class_java_lang_Character =
+                 load_class_bootstrap(utf_java_lang_Character)))
+               return false;
 
-/* loader_init *****************************************************************
+       if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
+               return false;
 
-   Initializes all lists and loads all classes required for the system
-   or the compiler.
+       if (!(class_java_lang_Integer =
+                 load_class_bootstrap(utf_java_lang_Integer)))
+               return false;
 
-*******************************************************************************/
-bool loader_init(u1 *stackbottom)
-{
-       classpath_info *cpi;
+       if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
+               return false;
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       /* Initialize the monitor pointer for zip/jar file locking.               */
+       if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
+               return false;
 
-       for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
-               if (cpi->type == CLASSPATH_ARCHIVE)
-                       initObjectLock(&cpi->header);
-       }
-#endif
+       if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
+               return false;
 
-       /* load some important classes */
 
-       if (!class_load(class_java_lang_Object))
+       /* load some other important classes */
+
+       if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
+               return false;
+
+       if (!(class_java_lang_ClassLoader =
+                 load_class_bootstrap(utf_java_lang_ClassLoader)))
+               return false;
+
+       if (!(class_java_lang_SecurityManager =
+                 load_class_bootstrap(utf_java_lang_SecurityManager)))
+               return false;
+
+       if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
+               return false;
+
+       if (!(class_java_lang_Thread =
+                 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
+               return false;
+
+       if (!(class_java_lang_ThreadGroup =
+                 load_class_bootstrap(utf_java_lang_ThreadGroup)))
+               return false;
+
+       if (!(class_java_lang_VMThread =
+                 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
+               return false;
+
+
+       /* some classes which may be used more often */
+
+       if (!(class_java_lang_StackTraceElement =
+                 load_class_bootstrap(utf_java_lang_StackTraceElement)))
+               return false;
+
+       if (!(class_java_lang_reflect_Constructor =
+                 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
+               return false;
+
+       if (!(class_java_lang_reflect_Field =
+                 load_class_bootstrap(utf_java_lang_reflect_Field)))
+               return false;
+
+       if (!(class_java_lang_reflect_Method =
+                 load_class_bootstrap(utf_java_lang_reflect_Method)))
                return false;
 
-       if (!class_load(class_java_lang_String))
+       if (!(class_java_security_PrivilegedAction =
+                 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
                return false;
 
-       if (!class_load(class_java_lang_Cloneable))
+       if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
                return false;
 
-       if (!class_load(class_java_io_Serializable))
+       if (!(arrayclass_java_lang_Object =
+                 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
                return false;
 
 #if defined(USE_THREADS)
@@ -390,8 +362,7 @@ static float suck_float(classbuffer *cb)
 #endif
 
        if (sizeof(float) != 4) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible float-format");
+               *exceptionptr = new_internalerror("Incompatible float-format");
 
                /* XXX should we exit in such a case? */
                throw_exception_exit();
@@ -410,8 +381,21 @@ static double suck_double(classbuffer *cb)
        u1 buffer[8];
        u2 i;   
 
+#if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
+       /*
+        * On little endian ARM processors when using FPA, word order
+        * of doubles is still big endian. So take that into account
+        * here. When using VFP, word order of doubles follows byte
+        * order. (michi 2005/07/24)
+        */
+       for (i = 0; i < 4; i++)
+               buffer[3 - i] = suck_u1(cb);
+       for (i = 0; i < 4; i++)
+               buffer[7 - i] = suck_u1(cb);
+#else
        for (i = 0; i < 8; i++)
                buffer[7 - i] = suck_u1(cb);
+#endif /* defined(__ARM__) && ... */
 
        memcpy((u1*) (&d), buffer, 8);
 #else 
@@ -419,8 +403,7 @@ static double suck_double(classbuffer *cb)
 #endif
 
        if (sizeof(double) != 8) {
-               *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                         "Incompatible double-format");
+               *exceptionptr = new_internalerror("Incompatible double-format");
 
                /* XXX should we exit in such a case? */
                throw_exception_exit();
@@ -512,6 +495,11 @@ void suck_init(char *classpath)
                                        cpi->next = NULL;
                                        cpi->path = filename;
                                        cpi->pathlen = filenamelen;
+
+                                       /* SUN compatible -verbose:class output */
+
+                                       if (opt_verboseclass)
+                                               printf("[Opened %s]\n", filename);
                                }
 
 #else
@@ -558,9 +546,16 @@ void suck_init(char *classpath)
 }
 
 
-void create_all_classes()
+/* loader_load_all_classes *****************************************************
+
+   Loads all classes specified in the BOOTCLASSPATH.
+
+*******************************************************************************/
+
+void loader_load_all_classes(void)
 {
        classpath_info *cpi;
+       classinfo      *c;
 
        for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
 #if defined(USE_ZLIB)
@@ -572,7 +567,13 @@ void create_all_classes()
                        ce = s->cacao_dir_list;
                                
                        while (ce) {
-                               (void) class_new(ce->name);
+                               /* skip all entries in META-INF and .properties, .png files */
+
+                               if (strncmp(ce->name->text, "META-INF", strlen("META-INF")) &&
+                                       !strstr(ce->name->text, ".properties") &&
+                                       !strstr(ce->name->text, ".png"))
+                                       c = load_class_bootstrap(ce->name);
+
                                ce = ce->next;
                        }
 
@@ -637,9 +638,10 @@ classbuffer *suck_start(classinfo *c)
                                        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;
+                                               cb->size  = file_info.uncompressed_size;
+                                               cb->data  = MNEW(u1, cb->size);
+                                               cb->pos   = cb->data - 1;
+                                               cb->path  = cpi->path;
 
                                                len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
 
@@ -680,9 +682,10 @@ classbuffer *suck_start(classinfo *c)
                                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;
+                                       cb->size  = buffer.st_size;
+                                       cb->data  = MNEW(u1, cb->size);
+                                       cb->pos   = cb->data - 1;
+                                       cb->path  = cpi->path;
 
                                        /* read class data */
                                        len = fread(cb->data, 1, cb->size, classfile);
@@ -705,9 +708,17 @@ classbuffer *suck_start(classinfo *c)
        }
 
        if (opt_verbose)
-               if (!found)
+               if (!found) {
                        dolog("Warning: Can not open class file '%s'", filename);
 
+                       if (strcmp(filename, "org/mortbay/util/MultiException.class") == 0) {
+                               static int i = 0;
+                               i++;
+                               if (i == 3)
+                                       assert(0);
+                       }
+               }
+
        MFREE(filename, char, filenamelen);
 
        return cb;
@@ -755,17 +766,7 @@ void fprintflags (FILE *fp, u2 f)
 
 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");
+       fprintflags(stdout,f);
 }
 
 
@@ -822,71 +823,6 @@ static bool skipattributes(classbuffer *cb, u4 num)
 }
 
 
-/******************** 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
@@ -895,7 +831,7 @@ u4 class_constanttype(classinfo *c, u4 pos)
 
 *******************************************************************************/
 
-static bool load_constantpool(classbuffer *cb)
+static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
 {
 
        /* The following structures are used to save information which cannot be 
@@ -997,7 +933,7 @@ static bool load_constantpool(classbuffer *cb)
 
                switch (t) {
                case CONSTANT_Class:
-                       nfc = NEW(forward_class);
+                       nfc = DNEW(forward_class);
 
                        nfc->next = forward_classes;
                        forward_classes = nfc;
@@ -1013,7 +949,7 @@ static bool load_constantpool(classbuffer *cb)
                        break;
                        
                case CONSTANT_String:
-                       nfs = NEW(forward_string);
+                       nfs = DNEW(forward_string);
                                
                        nfs->next = forward_strings;
                        forward_strings = nfs;
@@ -1030,7 +966,7 @@ static bool load_constantpool(classbuffer *cb)
                        break;
 
                case CONSTANT_NameAndType:
-                       nfn = NEW(forward_nameandtype);
+                       nfn = DNEW(forward_nameandtype);
                                
                        nfn->next = forward_nameandtypes;
                        forward_nameandtypes = nfn;
@@ -1053,7 +989,7 @@ static bool load_constantpool(classbuffer *cb)
                case CONSTANT_Fieldref:
                case CONSTANT_Methodref:
                case CONSTANT_InterfaceMethodref:
-                       nff = NEW(forward_fieldmethint);
+                       nff = DNEW(forward_fieldmethint);
                        
                        nff->next = forward_fieldmethints;
                        forward_fieldmethints = nff;
@@ -1176,8 +1112,8 @@ static bool load_constantpool(classbuffer *cb)
                        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");
+                               *exceptionptr = new_classformaterror(c,"Invalid UTF-8 string");
+                               return false;
                        }
                        /* insert utf-string into the utf-symboltable */
                        cpinfos[idx] = utf_new_intern((char *) (cb->pos + 1), length);
@@ -1201,37 +1137,45 @@ static bool load_constantpool(classbuffer *cb)
        while (forward_classes) {
                utf *name =
                        class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+               if (!name)
+                       return false;
+
+               if (opt_verify && !is_valid_name_utf(name)) {
+                       *exceptionptr = 
+                               new_classformaterror(c, "Class reference with invalid name");
+                       return false;
+               }
 
-               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 (!class_load(tc))
+                       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;
@@ -1239,7 +1183,6 @@ static bool load_constantpool(classbuffer *cb)
                
                nfs = forward_strings;
                forward_strings = forward_strings->next;
-               FREE(nfs, forward_string);
        }
 
        while (forward_nameandtypes) {
@@ -1254,10 +1197,14 @@ static bool load_constantpool(classbuffer *cb)
                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;
 
                if (opt_verify) {
                        /* check name */
@@ -1273,8 +1220,7 @@ static bool load_constantpool(classbuffer *cb)
                        /* disallow referencing <clinit> among others */
                        if (cn->name->text[0] == '<' && cn->name != utf_init) {
                                *exceptionptr =
-                                       new_exception_utfmessage(string_java_lang_InternalError,
-                                                                                        cn->name);
+                                       new_classformaterror(c,"Illegal reference to special method");
                                return false;
                        }
                }
@@ -1284,7 +1230,6 @@ static bool load_constantpool(classbuffer *cb)
 
                nfn = forward_nameandtypes;
                forward_nameandtypes = forward_nameandtypes->next;
-               FREE(nfn, forward_nameandtype);
        }
 
        while (forward_fieldmethints) {
@@ -1296,33 +1241,29 @@ static bool load_constantpool(classbuffer *cb)
                        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;
 
                cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
                cpinfos[forward_fieldmethints->thisindex] = fmi;
        
-               switch (forward_fieldmethints->tag) {
-               case CONSTANT_Fieldref:  /* check validity of descriptor */
-                       checkfielddescriptor(fmi->descriptor->text,
-                                                                utf_end(fmi->descriptor));
-                       break;
-               case CONSTANT_InterfaceMethodref:
-               case CONSTANT_Methodref: /* check validity of descriptor */
-                       checkmethoddescriptor(c, fmi->descriptor);
-                       break;
-               }
-       
                nff = forward_fieldmethints;
                forward_fieldmethints = forward_fieldmethints->next;
-               FREE(nff, forward_fieldmethint);
        }
 
        /* everything was ok */
@@ -1341,7 +1282,7 @@ static bool load_constantpool(classbuffer *cb)
 
 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
 
-static bool load_field(classbuffer *cb, fieldinfo *f)
+static bool load_field(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
 {
        classinfo *c;
        u4 attrnum, i;
@@ -1358,11 +1299,24 @@ static bool load_field(classbuffer *cb, fieldinfo *f)
 
        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))
+               return false;
+
+       /* descriptor_pool_add accepts method descriptors, so we have to check */
+       /* against them here before the call of desc_to_type below.            */
+       if (u->text[0] == '(') {
+               *exceptionptr = new_classformaterror(c,"Method descriptor used for field");
+               return false;
+       }
 
        if (opt_verify) {
                /* check name */
@@ -1396,9 +1350,6 @@ static bool load_field(classbuffer *cb, fieldinfo *f)
                                return false;
                        }
                }
-
-               /* check descriptor */
-               checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
        }
                
        f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
@@ -1529,10 +1480,10 @@ static bool load_field(classbuffer *cb, fieldinfo *f)
        
 *******************************************************************************/
 
-static bool load_method(classbuffer *cb, methodinfo *m)
+static bool load_method(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
 {
        classinfo *c;
-       s4 argcount;
+       int argcount;
        s4 i, j;
        u4 attrnum;
        u4 codeattrnum;
@@ -1562,23 +1513,31 @@ static bool load_method(classbuffer *cb, methodinfo *m)
 
        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))
+               return false;
 
        if (opt_verify) {
-               if (!is_valid_name_utf(m->name))
-                       panic("Method with invalid name");
+               if (!is_valid_name_utf(m->name)) {
+                       *exceptionptr = new_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) {
+                       *exceptionptr = new_classformaterror(c,"Method with invalid special name");
+                       return false;
+               }
        }
        
-       argcount = checkmethoddescriptor(c, m->descriptor);
-
        if (!(m->flags & ACC_STATIC))
                argcount++; /* count the 'this' argument */
 
@@ -1624,8 +1583,11 @@ static bool load_method(classbuffer *cb, methodinfo *m)
 
                        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)) {
+                                       *exceptionptr = new_classformaterror(c,
+                                                       "Instance initialization method has invalid flags set");
+                                       return false;
+                               }
                        }
                }
        }
@@ -1649,21 +1611,6 @@ static bool load_method(classbuffer *cb, methodinfo *m)
 
        m->xta = NULL;
 
-#if 0
-       if (!(m->flags & ACC_NATIVE)) {
-               m->stubroutine = createcompilerstub(m);
-
-       } else {
-               functionptr f = native_findfunction(c->name,
-                                                                                               m->name, m->descriptor, 
-                                                                                               (m->flags & ACC_STATIC));
-#if defined(STATIC_CLASSPATH)
-               if (f)
-#endif
-                       m->stubroutine = createnativestub(f, m);
-       }
-#endif
-
        if (!check_classbuffer_size(cb, 2))
                return false;
        
@@ -1757,11 +1704,12 @@ static bool load_method(classbuffer *cb, methodinfo *m)
 
                                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;
                                }
                        }
@@ -1830,11 +1778,12 @@ static bool load_method(classbuffer *cb, methodinfo *m)
                        if (!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;
                        }
                                
@@ -1910,9 +1859,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);
@@ -1949,119 +1898,265 @@ static bool load_attributes(classbuffer *cb, u4 num)
 }
 
 
-/***************** Function: print_arraydescriptor ****************************
+/* 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
 
-       Debugging helper for displaying an arraydescriptor
-       
 *******************************************************************************/
 
-void print_arraydescriptor(FILE *file, arraydescriptor *desc)
+classinfo *load_class_from_sysloader(utf *name)
 {
-       if (!desc) {
-               fprintf(file, "<NULL>");
-               return;
-       }
+       methodinfo        *m;
+       java_objectheader *cl;
+       classinfo         *r;
+
+#ifdef LOADER_VERBOSE
+       char logtext[MAXLOGTEXT];
+       LOADER_INDENT(logtext);
+       sprintf(logtext+strlen(logtext),"load_class_from_sysloader(");
+       utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
+       log_text(logtext);
+#endif
 
-       fprintf(file, "{");
-       if (desc->componentvftbl) {
-               if (desc->componentvftbl->class)
-                       utf_fprint(file, desc->componentvftbl->class->name);
-               else
-                       fprintf(file, "<no classinfo>");
-       }
-       else
-               fprintf(file, "0");
-               
-       fprintf(file, ",");
-       if (desc->elementvftbl) {
-               if (desc->elementvftbl->class)
-                       utf_fprint(file, desc->elementvftbl->class->name);
-               else
-                       fprintf(file, "<no classinfo>");
-       }
-       else
-               fprintf(file, "0");
-       fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
-                       desc->dataoffset, desc->componentsize);
+       LOADER_ASSERT(class_java_lang_Object);
+       LOADER_ASSERT(class_java_lang_ClassLoader);
+       LOADER_ASSERT(class_java_lang_ClassLoader->linked);
+       
+       m = class_resolveclassmethod(class_java_lang_ClassLoader,
+                                                                utf_getSystemClassLoader,
+                                                                utf_void__java_lang_ClassLoader,
+                                                                class_java_lang_Object,
+                                                                false);
+
+       if (!m)
+               return false;
+
+       cl = (java_objectheader *) asm_calljavafunction(m, NULL, NULL, NULL, NULL);
+       if (!cl)
+               return false;
+
+       LOADER_INC();
+       r = load_class_from_classloader(name, cl);
+       LOADER_DEC();
+
+       return r;
 }
 
+/* load_class_from_classloader *************************************************
 
-/********************** Function: class_load ***********************************
-       
-       Loads everything interesting about a class from the class file. The
-       'classinfo' structure must have been allocated previously.
+   Load the class with the given name using the given user-defined class loader.
 
-       The super class and the interfaces implemented by this class need not be
-       loaded. The link is set later by the function 'class_link'.
+   IN:
+       name.............the classname
+          cl...............user-defined class loader
+          
+   RETURN VALUE:
+       the loaded class, or
+          NULL if an exception has been thrown
 
-       The loaded class is removed from the list 'unloadedclasses' and added to
-       the list 'unlinkedclasses'.
-       
 *******************************************************************************/
 
-classinfo *class_load_intern(classbuffer *cb);
-
-/*  classinfo *load_class_from_classloader(java_objectheader *cl, classinfo *c) */
-classinfo *class_load_extern(classinfo *rc, classinfo *c)
+classinfo *load_class_from_classloader(utf *name, java_objectheader *cl)
 {
        classinfo *r;
 
-       /* if other class loader than bootstrap, call it */
-
-       if (rc->classloader) {
-               methodinfo *lc;
+#ifdef LOADER_VERBOSE
+       char logtext[MAXLOGTEXT];
+       LOADER_INDENT(logtext);
+       strcat(logtext,"load_class_from_classloader(");
+       utf_sprint(logtext+strlen(logtext),name);sprintf(logtext+strlen(logtext),",%p,",(void*)cl);
+       if (!cl) strcat(logtext,"<bootstrap>");
+       else if (cl->vftbl && cl->vftbl->class) utf_sprint(logtext+strlen(logtext),cl->vftbl->class->name);
+       else strcat(logtext,"<unknown class>");
+       strcat(logtext,")");
+       log_text(logtext);
+#endif
 
-/*             printf("DefineClass: name="); */
-/*             utf_display(c->name); */
-/*             printf(" loader="); */
-/*             utf_display(rc->classloader->vftbl->class->name); */
-/*             printf("\n"); */
+       LOADER_ASSERT(name);
 
-               lc = class_resolveclassmethod(rc->classloader->vftbl->class,
-                                                                        utf_loadClass,
-                                                                        utf_java_lang_String__java_lang_Class,
-                                                                        class_java_lang_Object,
-                                                                        true);
+       /* lookup if this class has already been loaded */
 
-               if (!lc)
-                       return NULL;
+       r = classcache_lookup(cl, name);
 
-               r = (classinfo *) asm_calljavafunction(lc,
-                                                                                          rc->classloader,
-                                                                                          javastring_new(c->name),
-                                                                                          NULL, NULL);
+#ifdef LOADER_VERBOSE
+       if (r)
+               dolog("        cached -> %p",(void*)r);
+#endif
 
+       if (r)
                return r;
 
-       } else {
-               return class_load(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_classnotfoundexception(name);
+                                       return false;
+                               }
 
-classinfo *class_load(classinfo *c)
-{
-       classbuffer *cb;
-       classinfo *r;
+                               u = utf_new(text + 2, namelen - 3);
 
-#if defined(USE_THREADS)
-       /* enter a monitor on the class */
+                               if (!(comp = load_class_from_classloader(u, cl)))
+                                       return false;
 
-       builtin_monitorenter((java_objectheader *) c);
-#endif
+                               /* create the array class */
+                               return class_array_of(comp, false);
 
-       /* maybe the class is already loaded */
+                       case '[':
+                               /* load the component class */
 
-       if (c->loaded) {
-#if defined(USE_THREADS)
-               builtin_monitorexit((java_objectheader *) c);
-#endif
+                               u = utf_new(text + 1, namelen - 1);
 
-               return c;
-       }
+                               if (!(comp = load_class_from_classloader(u, cl)))
+                                       return false;
 
-#if defined(STATISTICS)
-       /* measure time */
+                               /* create the array class */
+                               return class_array_of(comp, false);
+
+                       default:
+                               /* primitive array classes are loaded by the bootstrap loader */
+                               return load_class_bootstrap(name);
+                       }
+               }
+               
+               LOADER_ASSERT(class_java_lang_Object);
+
+               lc = class_resolveclassmethod(cl->vftbl->class,
+                                                                         utf_loadClass,
+                                                                         utf_java_lang_String__java_lang_Class,
+                                                                         class_java_lang_Object,
+                                                                         true);
+
+               if (!lc)
+                       return false; /* exception */
+
+               LOADER_INC();
+               r = (classinfo *) asm_calljavafunction(lc,
+                                                                                          cl,
+                                                                                          javastring_new_slash_to_dot(name),
+                                                                                          NULL, NULL);
+               LOADER_DEC();
+
+               if (r) {
+                       /* 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. */
+
+                   classinfo *c = classcache_store(cl,r,false);
+
+                       if (c == NULL) {
+                               /* exception, free the loaded class */
+                               r->loaded = false;
+                               class_free(r);
+                       }
+
+                       r = c;
+               }
+
+               /* SUN compatible -verbose:class output */
+
+               if (opt_verboseclass && (r != NULL) && (r->classloader == cl)) {
+                       printf("[Loaded ");
+                       utf_display_classname(name);
+                       printf("]\n");
+               }
+
+               return r;
+       } 
+
+       LOADER_INC();
+       r = load_class_bootstrap(name);
+       LOADER_DEC();
+
+       return r;
+}
+
+
+/* load_class_bootstrap ********************************************************
+       
+   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(utf *name)
+{
+       classbuffer *cb;
+       classinfo   *c;
+       classinfo   *r;
+#ifdef LOADER_VERBOSE
+       char logtext[MAXLOGTEXT];
+#endif
+
+       /* for debugging */
+
+       LOADER_ASSERT(name);
+       LOADER_INC();
+
+       /* lookup if this class has already been loaded */
+
+       if ((r = classcache_lookup(NULL, name)))
+               goto success;
+
+#ifdef LOADER_VERBOSE
+       LOADER_INDENT(logtext);
+       strcat(logtext,"load_class_bootstrap(");
+       utf_sprint(logtext+strlen(logtext),name);strcat(logtext,")");
+       log_text(logtext);
+#endif
+
+       /* 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)
+                       goto return_exception;
+               LOADER_ASSERT(c->loaded);
+               r = c;
+               goto success;
+       }
+
+#if defined(STATISTICS)
+       /* measure time */
 
        if (getcompilingtime)
                compilingtime_stop();
@@ -2073,34 +2168,52 @@ classinfo *class_load(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
-
-               return NULL;
+                                                                        name);
+               goto return_exception;
        }
        
-       /* call the internal function */
-       r = class_load_intern(cb);
+       /* load the class from the buffer */
+
+       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. */
+
+               classinfo *res = classcache_store(NULL, c, true);
+
+               if (!res) {
+                       /* exception */
+                       class_free(c);
+               }
+
+               r = res;
+       }
+
+       /* SUN compatible -verbose:class output */
 
-               /* now free the allocated memory, otherwise we could ran into a DOS */
-               class_remove(c);
+       if (opt_verboseclass && r) {
+               printf("[Loaded ");
+               utf_display_classname(name);
+               printf(" from %s]\n", cb->path);
        }
 
        /* free memory */
+
        suck_stop(cb);
 
 #if defined(STATISTICS)
@@ -2113,54 +2226,102 @@ classinfo *class_load(classinfo *c)
                compilingtime_start();
 #endif
 
-#if defined(USE_THREADS)
-       /* leave the monitor */
+       if (!r)
+               goto return_exception;
 
-       builtin_monitorexit((java_objectheader *) c);
-#endif
+success:
+       LOADER_DEC();
 
        return r;
+
+return_exception:
+       LOADER_DEC();
+
+       return NULL;
 }
 
 
-classinfo *class_load_intern(classbuffer *cb)
+/* load_class_from_classbuffer *************************************************
+       
+   Loads everything interesting about a class from the class file. The
+   'classinfo' structure must have been allocated previously.
+
+   The super class and the interfaces implemented by this class need
+   not be loaded. The link is set later by the function 'class_link'.
+
+   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;
-       char msg[MAXLOGTEXT];               /* maybe we get an exception */
+       s4 dumpsize;
+       descriptor_pool *descpool;
+#if defined(STATISTICS)
+       u4 classrefsize;
+       u4 descsize;
+#endif
+#ifdef LOADER_VERBOSE
+       char logtext[MAXLOGTEXT];
+#endif
 
        /* get the classbuffer's class */
+
        c = cb->class;
 
        /* maybe the class is already loaded */
+
        if (c->loaded)
                return c;
 
+#ifdef LOADER_VERBOSE
+       LOADER_INDENT(logtext);
+       strcat(logtext,"load_class_from_classbuffer(");
+       utf_sprint(logtext+strlen(logtext),c->name);strcat(logtext,")");
+       log_text(logtext);
+       LOADER_INC();
+#endif
+
 #if defined(STATISTICS)
        if (opt_stat)
                count_class_loads++;
 #endif
 
        /* output for debugging purposes */
+
        if (loadverbose)
                log_message_class("Loading class: ", c);
        
+       /* mark start of dump memory area */
+
+       dumpsize = dump_size();
+
        /* class is somewhat loaded */
+
        c->loaded = true;
 
        if (!check_classbuffer_size(cb, 4 + 2 + 2))
-               return NULL;
+               goto return_exception;
 
        /* check signature */
+
        if (suck_u4(cb) != MAGIC) {
                *exceptionptr = new_classformaterror(c, "Bad magic number");
 
-               return NULL;
+               goto return_exception;
        }
 
        /* check version */
+
        mi = suck_u2(cb);
        ma = suck_u2(cb);
 
@@ -2170,12 +2331,17 @@ classinfo *class_load_intern(classbuffer *cb)
                                                                                         "Unsupported major.minor version %d.%d",
                                                                                         ma, mi);
 
-               return NULL;
+               goto return_exception;
        }
 
+       /* create a new descriptor pool */
+
+       descpool = descriptor_pool_new(c);
+
        /* load the constant pool */
-       if (!load_constantpool(cb))
-               return NULL;
+
+       if (!load_constantpool(cb, descpool))
+               goto return_exception;
 
        /*JOWENN*/
        c->erroneous_state = 0;
@@ -2185,20 +2351,20 @@ classinfo *class_load_intern(classbuffer *cb)
        c->impldBy = NULL;
 
        /* ACC flags */
+
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               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) {
@@ -2206,7 +2372,7 @@ classinfo *class_load_intern(classbuffer *cb)
                                new_classformaterror(c,
                                                                         "Illegal class modifiers: 0x%X", c->flags);
 
-                       return NULL;
+                       goto return_exception;
                }
 
                if (c->flags & ACC_SUPER) {
@@ -2218,105 +2384,253 @@ classinfo *class_load_intern(classbuffer *cb)
                *exceptionptr =
                        new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
 
-               return NULL;
+               goto return_exception;
        }
 
        if (!check_classbuffer_size(cb, 2 + 2))
-               return NULL;
+               goto return_exception;
 
        /* this class */
+
        i = suck_u2(cb);
-       if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
-               return NULL;
+       if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
+               goto return_exception;
+
+       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);
 
-       if (tc != c) {
                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);
 
-               return NULL;
+               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)))
-                       return NULL;
+               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,
                                                                          "java.lang.Object with superclass");
 
-                       return NULL;
+                       goto return_exception;
                }
 
                /* 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");
 
-                       return NULL;
+                       goto return_exception;
                }
 
        } 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");
 
-                       return NULL;
+                       goto return_exception;
                }
        }
                         
        /* retrieve interfaces */
+
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->interfacescount = suck_u2(cb);
 
        if (!check_classbuffer_size(cb, 2 * c->interfacescount))
-               return NULL;
+               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)))
-                       return NULL;
+               /* 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))
-               return NULL;
+               goto return_exception;
 
        c->fieldscount = suck_u2(cb);
        c->fields = GCNEW(fieldinfo, c->fieldscount);
 /*     c->fields = MNEW(fieldinfo, c->fieldscount); */
        for (i = 0; i < c->fieldscount; i++) {
-               if (!load_field(cb, &(c->fields[i])))
-                       return NULL;
+               if (!load_field(cb, &(c->fields[i]),descpool))
+                       goto return_exception;
        }
 
        /* load methods */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->methodscount = suck_u2(cb);
 /*     c->methods = GCNEW(methodinfo, c->methodscount); */
        c->methods = MNEW(methodinfo, c->methodscount);
        for (i = 0; i < c->methodscount; i++) {
-               if (!load_method(cb, &(c->methods[i])))
-                       return NULL;
+               if (!load_method(cb, &(c->methods[i]),descpool))
+                       goto return_exception;
+       }
+
+       /* create the class reference table */
+
+       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));
+
+#if defined(STATISTICS)
+       if (opt_stat) {
+               descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
+               count_classref_len += classrefsize;
+               count_parsed_desc_len += descsize;
+       }
+#endif
+
+       /* 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);
+               if (!c->fields[i].parseddesc)
+                       goto return_exception;
+       }
+
+       /* parse method descriptors */
+
+       for (i = 0; i < c->methodscount; i++) {
+               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;
+               }
        }
 
        /* 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.
@@ -2365,7 +2679,7 @@ classinfo *class_load_intern(classbuffer *cb)
                                                        new_classformaterror(c,
                                                                                                 "Repetitive field name/signature");
 
-                                               return NULL;
+                                               goto return_exception;
                                        }
                                } while ((old = next[old]));
                        }
@@ -2399,7 +2713,7 @@ classinfo *class_load_intern(classbuffer *cb)
                                                        new_classformaterror(c,
                                                                                                 "Repetitive method name/signature");
 
-                                               return NULL;
+                                               goto return_exception;
                                        }
                                } while ((old = next[old]));
                        }
@@ -2418,11 +2732,12 @@ classinfo *class_load_intern(classbuffer *cb)
 #endif
 
        /* load attribute structures */
+
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        if (!load_attributes(cb, suck_u2(cb)))
-               return NULL;
+               goto return_exception;
 
 #if 0
        /* Pre java 1.5 version don't check this. This implementation is like
@@ -2436,132 +2751,231 @@ classinfo *class_load_intern(classbuffer *cb)
                if (classdata_left > 0) {
                        *exceptionptr =
                                new_classformaterror(c, "Extra bytes at the end of class file");
-                       return NULL;
+                       goto return_exception;
                }
        }
 #endif
 
+       /* release dump area */
+
+       dump_release(dumpsize);
+       
        if (loadverbose)
                log_message_class("Loading done class: ", c);
 
+       LOADER_DEC();
        return c;
+
+return_exception:
+       /* release dump area */
+
+       dump_release(dumpsize);
+
+       /* an exception has been thrown */
+
+       LOADER_DEC();
+       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;
-       int namelen;
+       classinfo         *comp = NULL;
+       methodinfo        *clone;
+       methoddesc        *clonedesc;
+       constant_classref *classrefs;
+       char              *text;
+       s4                 namelen;
+       utf               *u;
+
+#ifdef LOADER_VERBOSE
+       char logtext[MAXLOGTEXT];
+       LOADER_INDENT(logtext);
+       strcat(logtext,"load_newly_created_array(");utf_sprint_classname(logtext+strlen(logtext),c->name);
+       sprintf(logtext+strlen(logtext),") loader=%p",loader);
+       log_text(logtext);
+#endif
 
-       /* 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_classnotfoundexception(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));
-                       class_load(comp);
-                       list_addfirst(&unlinkedclasses, comp);
 
-               } else {
-                       comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
+               u = utf_new_intern(text + 1, namelen - 1);
+               LOADER_INC();
+               if (!(comp = load_class_from_classloader(u, loader))) {
+                       LOADER_DEC();
+                       return NULL;
                }
+               LOADER_DEC();
+               LOADER_ASSERT(comp->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));
-                       class_load(comp);
-                       list_addfirst(&unlinkedclasses, comp);
+               /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+               if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+                       *exceptionptr = new_classnotfoundexception(c->name);
+                       return NULL;
+               }
 
-               } else {
-                       comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
+               u = utf_new_intern(text + 2, namelen - 3);
+
+               LOADER_INC();
+               if (!(comp = load_class_from_classloader(u, loader))) {
+                       LOADER_DEC();
+                       return NULL;
                }
+               LOADER_DEC();
+               LOADER_ASSERT(comp->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;
+
+       default:
+               /* c is an array of a primitive type */
+
+               /* check for cases like `[II' */
+               if (namelen > 2) {
+                       *exceptionptr = new_classnotfoundexception(c->name);
+                       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;
        }
 
-       /* Setup the array class */
-       c->super = class_java_lang_Object;
-       c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+       LOADER_ASSERT(class_java_lang_Object);
+       LOADER_ASSERT(class_java_lang_Cloneable);
+       LOADER_ASSERT(class_java_io_Serializable);
+
+       /* setup the array class */
+
+       c->super.cls = class_java_lang_Object;
 
     c->interfacescount = 2;
-    c->interfaces = MNEW(classinfo*, 2);
+    c->interfaces = MNEW(classref_or_classinfo, 2);
 
        if (opt_eager) {
                classinfo *tc;
 
-               tc = class_new_intern(utf_new_char("java/lang/Cloneable"));
-               class_load(tc);
+               tc = class_java_lang_Cloneable;
+               LOADER_ASSERT(tc->loaded);
                list_addfirst(&unlinkedclasses, tc);
-               c->interfaces[0] = tc;
+               c->interfaces[0].cls = tc;
 
-               tc = class_new_intern(utf_new_char("java/io/Serializable"));
-               class_load(tc);
+               tc = class_java_io_Serializable;
+               LOADER_ASSERT(tc->loaded);
                list_addfirst(&unlinkedclasses, tc);
-               c->interfaces[1] = tc;
+               c->interfaces[1].cls = tc;
 
        } else {
-               c->interfaces[0] = class_new(utf_new_char("java/lang/Cloneable"));
-               c->interfaces[1] = class_new(utf_new_char("java/io/Serializable"));
+               c->interfaces[0].cls = class_java_lang_Cloneable;
+               c->interfaces[1].cls = class_java_io_Serializable;
        }
 
        c->methodscount = 1;
        c->methods = MNEW(methodinfo, c->methodscount);
 
+       classrefs = MNEW(constant_classref, 2);
+       CLASSREF_INIT(classrefs[0], c, c->name);
+       CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
+
+       /* 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;
+
+       /* create methodinfo */
+
        clone = c->methods;
-       memset(clone, 0, sizeof(methodinfo));
-       clone->flags = ACC_PUBLIC;
-       clone->name = utf_new_char("clone");
-       clone->descriptor = utf_new_char("()Ljava/lang/Object;");
+       MSET(clone, 0, methodinfo, 1);
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       initObjectLock(&clone->header);
+#endif
+
+       /* 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->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
        clone->monoPoly = MONO;
 
-       /* XXX: field: length? */
-
-       /* array classes are not loaded from class files */
-       c->loaded = true;
-}
+       /* parse the descriptor to get the register allocation */
 
+       if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
+               return false;
 
-/************************* Function: class_findfield ***************************
-       
-       Searches a 'classinfo' structure for a field having the given name and
-       type.
+       clone->entrypoint =
+               codegen_createnativestub((functionptr) &builtin_clone_array, clone);
 
-*******************************************************************************/
+       /* XXX: field: length? */
 
-fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
+       /* array classes are not loaded from class files */
 
-       for (i = 0; i < c->fieldscount; i++) { 
-               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
-                       return &(c->fields[i]);                                                         
-    }
+       c->loaded = true;
+       c->parseddescs = (u1 *) clonedesc;
+       c->parseddescsize = sizeof(methodinfo);
+       c->classrefs = classrefs;
+       c->classrefcount = 1;
 
-       panic("Can not find field given in CONSTANT_Fieldref");
+       /* insert class into the loaded class cache */
+       /* XXX free classinfo if NULL returned? */
 
-       /* keep compiler happy */
-       return NULL;
+       return classcache_store(loader,c,true);
 }
 
 
@@ -2590,15 +3004,15 @@ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
        /* try superinterfaces recursively */
 
        for (i = 0; i < c->interfacescount; i++) {
-               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+               fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
                if (fi)
                        return fi;
        }
 
        /* try superclass */
 
-       if (c->super)
-               return class_resolvefield_int(c->super, name, desc);
+       if (c->super.cls)
+               return class_resolvefield_int(c->super.cls, name, desc);
 
        /* not found */
 
@@ -2650,7 +3064,7 @@ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 {
        methodinfo *m;
-       s4 i;
+       s4          i;
 
        for (i = 0; i < c->methodscount; i++) {
                m = &(c->methods[i]);
@@ -2663,29 +3077,6 @@ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 }
 
 
-/*********************** 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
@@ -2710,8 +3101,8 @@ methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
                                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 *desc_end = UTF_END(desc);         
+                               char *meth_end = UTF_END(meth_descr);   
                                char ch;
 
                                /* compare argument types */
@@ -2721,7 +3112,7 @@ methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
                                                break; /* no match */
 
                                        if (ch == ')')
-                                               return &(c->methods[i]);   /* all parameter types equal */
+                                               return &(c->methods[i]); /* all parameter types equal */
                                }
                        }
                }
@@ -2746,7 +3137,7 @@ methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
                /* method found */
                if (m) return m;
                /* search superclass */
-               c = c->super;
+               c = c->super.cls;
        }
 
        return NULL;
@@ -2757,6 +3148,8 @@ methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
        
    Searches a class and it's super classes for a method.
 
+   Superinterfaces are *not* searched.
+
 *******************************************************************************/
 
 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
@@ -2769,7 +3162,7 @@ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
                if (m)
                        return m;
 
-               c = c->super;
+               c = c->super.cls;
        }
 
        return NULL;
@@ -2786,7 +3179,7 @@ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
                                                                                                           utf *name, utf *desc)
 {
        methodinfo *m;
-       s4 i;
+       s4          i;
        
        m = class_findmethod(c, name, desc);
 
@@ -2796,7 +3189,8 @@ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
        /* try the superinterfaces */
 
        for (i = 0; i < c->interfacescount; i++) {
-               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
+                                                                                               name, desc);
 
                if (m)
                        return m;
@@ -2837,6 +3231,7 @@ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
                return mi;
 
        /* try class java.lang.Object */
+
        mi = class_findmethod(class_java_lang_Object, name, desc);
 
        if (mi)
@@ -2852,11 +3247,11 @@ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
 
 /* class_resolveclassmethod ****************************************************
        
-    Resolves a reference from REFERER to a method with NAME and DESC in
-    class C.
+   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.
+   If the method cannot be resolved the return value is NULL. If
+   EXCEPT is true *exceptionptr is set, too.
 
 *******************************************************************************/
 
@@ -2889,13 +3284,14 @@ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
                if (mi)
                        goto found;
 
-               cls = cls->super;
+               cls = cls->super.cls;
        }
 
        /* try the superinterfaces */
 
        for (i = 0; i < c->interfacescount; i++) {
-               mi = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+               mi = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
+                                                                                                name, desc);
 
                if (mi)
                        goto found;
@@ -2945,206 +3341,8 @@ 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 */
-
-static classinfo *class_init_intern(classinfo *c)
-{
-       methodinfo *m;
-       s4 i;
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       int b;
-#endif
-
-       /* maybe the class is not already loaded */
-       if (!c->loaded)
-               if (!class_load(c))
-                       return NULL;
-
-       /* maybe the class is not already linked */
-       if (!c->linked)
-               if (!class_link(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;
-               }
-       }
-
-       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);
-
-#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;
-               }
-
-               return NULL;
+               sub = sub->super.cls;
        }
-
-       if (initverbose)
-               log_message_class("Finished static class initializer for class: ", c);
-
-       return c;
 }
 
 
@@ -3159,7 +3357,7 @@ void class_showconstanti(classinfo *c, int ii)
                switch (c->cptags [i]) {
                case CONSTANT_Class:
                        printf("Classreference -> ");
-                       utf_display(((classinfo*)e)->name);
+                       utf_display(((constant_classref*)e)->name);
                        break;
                                
                case CONSTANT_Fieldref:
@@ -3171,7 +3369,7 @@ void class_showconstanti(classinfo *c, int ii)
                displayFMIi:
                        {
                                constant_FMIref *fmi = e;
-                               utf_display(fmi->class->name);
+                               utf_display(fmi->classref->name);
                                printf(".");
                                utf_display(fmi->name);
                                printf(" ");
@@ -3217,7 +3415,8 @@ void class_showconstanti(classinfo *c, int ii)
                        utf_display(e);
                        break;
                default: 
-                       panic("Invalid type of ConstantPool-Entry");
+                       log_text("Invalid type of ConstantPool-Entry");
+                       assert(0);
                }
        }
        printf("\n");
@@ -3240,7 +3439,7 @@ void class_showconstantpool (classinfo *c)
                        switch (c -> cptags [i]) {
                        case CONSTANT_Class:
                                printf ("Classreference -> ");
-                               utf_display ( ((classinfo*)e) -> name );
+                               utf_display ( ((constant_classref*)e) -> name );
                                break;
                                
                        case CONSTANT_Fieldref:
@@ -3252,7 +3451,7 @@ void class_showconstantpool (classinfo *c)
                        displayFMI:
                                {
                                        constant_FMIref *fmi = e;
-                                       utf_display ( fmi->class->name );
+                                       utf_display ( fmi->classref->name );
                                        printf (".");
                                        utf_display ( fmi->name);
                                        printf (" ");
@@ -3298,7 +3497,8 @@ void class_showconstantpool (classinfo *c)
                                utf_display (e);
                                break;
                        default: 
-                               panic ("Invalid type of ConstantPool-Entry");
+                               log_text("Invalid type of ConstantPool-Entry");
+                               assert(0);
                        }
                }
 
@@ -3318,16 +3518,16 @@ void class_showmethods (classinfo *c)
        printf ("Flags: ");     printflags (c->flags);  printf ("\n");
 
        printf ("This: "); utf_display (c->name); printf ("\n");
-       if (c->super) {
-               printf ("Super: "); utf_display (c->super->name); printf ("\n");
+       if (c->super.cls) {
+               printf ("Super: "); utf_display (c->super.cls->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);
+               utf_display (c -> interfaces[i].cls -> name);
+               printf (" (%d)\n", c->interfaces[i].cls -> index);
                }
 
        printf ("fields:\n");           
@@ -3353,209 +3553,15 @@ void class_showmethods (classinfo *c)
 }
 
 
-/******************************************************************************/
-/******************* General functions for the class loader *******************/
-/******************************************************************************/
-
-/**************** function: class_primitive_from_sig ***************************
-
-       return the primitive class indicated by the given signature character
+/* loader_close ****************************************************************
 
-    If the descriptor does not indicate a valid primitive type the
-    return value is NULL.
-
-********************************************************************************/
-
-classinfo *class_primitive_from_sig(char sig)
-{
-       switch (sig) {
-         case 'I': return primitivetype_table[PRIMITIVETYPE_INT].class_primitive;
-         case 'J': return primitivetype_table[PRIMITIVETYPE_LONG].class_primitive;
-         case 'F': return primitivetype_table[PRIMITIVETYPE_FLOAT].class_primitive;
-         case 'D': return primitivetype_table[PRIMITIVETYPE_DOUBLE].class_primitive;
-         case 'B': return primitivetype_table[PRIMITIVETYPE_BYTE].class_primitive;
-         case 'C': return primitivetype_table[PRIMITIVETYPE_CHAR].class_primitive;
-         case 'S': return primitivetype_table[PRIMITIVETYPE_SHORT].class_primitive;
-         case 'Z': return primitivetype_table[PRIMITIVETYPE_BOOLEAN].class_primitive;
-         case 'V': return primitivetype_table[PRIMITIVETYPE_VOID].class_primitive;
-       }
-       return NULL;
-}
-
-/****************** function: class_from_descriptor ****************************
-
-    return the class indicated by the given descriptor
-
-    utf_ptr....first character of descriptor
-    end_ptr....first character after the end of the string
-    next.......if non-NULL, *next is set to the first character after
-               the descriptor. (Undefined if an error occurs.)
-
-    mode.......a combination (binary or) of the following flags:
-
-               (Flags marked with * are the default settings.)
-
-               What to do if a reference type descriptor is parsed successfully:
-
-                   CLASSLOAD_SKIP...skip it and return something != NULL
-                                * CLASSLOAD_NEW....get classinfo * via class_new
-                   CLASSLOAD_LOAD...get classinfo * via loader_load
-
-               How to handle primitive types:
-
-                            * CLASSLOAD_PRIMITIVE.......return primitive class (eg. "int")
-                   CLASSLOAD_NULLPRIMITIVE...return NULL for primitive types
-
-               How to handle "V" descriptors:
-
-                            * CLASSLOAD_VOID.....handle it like other primitive types
-                   CLASSLOAD_NOVOID...treat it as an error
-
-               How to deal with extra characters after the end of the
-               descriptor:
-
-                            * CLASSLOAD_NOCHECKEND...ignore (useful for parameter lists)
-                   CLASSLOAD_CHECKEND.....treat them as an error
-
-               How to deal with errors:
-
-                            * CLASSLOAD_PANIC....abort execution with an error message
-                   CLASSLOAD_NOPANIC..return NULL on error
-
-*******************************************************************************/
-
-classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
-                                                                char **next, int mode)
-{
-       char *start = utf_ptr;
-       bool error = false;
-       utf *name;
-
-       SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
-
-       if (mode & CLASSLOAD_CHECKEND)
-               error |= (utf_ptr != end_ptr);
-       
-       if (!error) {
-               if (next) *next = utf_ptr;
-               
-               switch (*start) {
-                 case 'V':
-                         if (mode & CLASSLOAD_NOVOID)
-                                 break;
-                         /* FALLTHROUGH! */
-                 case 'I':
-                 case 'J':
-                 case 'F':
-                 case 'D':
-                 case 'B':
-                 case 'C':
-                 case 'S':
-                 case 'Z':
-                         return (mode & CLASSLOAD_NULLPRIMITIVE)
-                                 ? NULL
-                                 : class_primitive_from_sig(*start);
-                         
-                 case 'L':
-                         start++;
-                         utf_ptr--;
-                         /* FALLTHROUGH! */
-                 case '[':
-                         if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
-                         name = utf_new(start, utf_ptr - start);
-                         if (opt_eager) {
-                                 classinfo *tc;
-
-                                 tc = class_new_intern(name);
-                                 class_load(tc);
-                                 list_addfirst(&unlinkedclasses, tc);
-
-                                 return tc;
-
-                         } else {
-                                 return (mode & CLASSLOAD_LOAD)
-                                         ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
-                         }
-               }
-       }
-
-       /* An error occurred */
-       if (mode & CLASSLOAD_NOPANIC)
-               return NULL;
-
-       log_plain("Invalid descriptor at beginning of '");
-       log_plain_utf(utf_new(start, end_ptr - start));
-       log_plain("'");
-       log_nl();
-                                                 
-       panic("Invalid descriptor");
-
-       /* keep compiler happy */
-       return NULL;
-}
-
-
-/******************* function: type_from_descriptor ****************************
-
-    return the basic type indicated by the given descriptor
-
-    This function parses a descriptor and returns its basic type as
-    TYPE_INT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_ADDRESS or TYPE_VOID.
-
-    cls...if non-NULL the referenced variable is set to the classinfo *
-          returned by class_from_descriptor.
-
-    For documentation of the arguments utf_ptr, end_ptr, next and mode
-    see class_from_descriptor. The only difference is that
-    type_from_descriptor always uses CLASSLOAD_PANIC.
-
-********************************************************************************/
-
-int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
-                                                char **next, int mode)
-{
-       classinfo *mycls;
-       if (!cls) cls = &mycls;
-       *cls = class_from_descriptor(utf_ptr, end_ptr, next, mode & (~CLASSLOAD_NOPANIC));
-       switch (*utf_ptr) {
-         case 'B': 
-         case 'C':
-         case 'I':
-         case 'S':  
-         case 'Z':
-                 return TYPE_INT;
-         case 'D':
-                 return TYPE_DOUBLE;
-         case 'F':
-                 return TYPE_FLOAT;
-         case 'J':
-                 return TYPE_LONG;
-         case 'V':
-                 return TYPE_VOID;
-       }
-       return TYPE_ADDRESS;
-}
-
-
-/******************** Function: 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 */
 }