Reentrant compiler fixes: moved global variables into struct codegendata
[cacao.git] / src / vm / loader.c
index 08af5051e9369cc14e9594b51da8088b5dc04e2a..86d8b4773ee54bbbdfa0a3e65c190976368783ca 100644 (file)
    Contact: cacao@complang.tuwien.ac.at
 
    Authors: Reinhard Grafl
    Contact: cacao@complang.tuwien.ac.at
 
    Authors: Reinhard Grafl
+
    Changes: Andreas Krall
             Roman Obermaiser
             Mark Probst
    Changes: Andreas Krall
             Roman Obermaiser
             Mark Probst
-                       Edwin Steiner
+            Edwin Steiner
+            Christian Thalinger
 
 
-   $Id: loader.c 951 2004-03-11 17:30:03Z jowenn $
+   $Id: loader.c 1329 2004-07-21 15:36:33Z twisti $
 
 */
 
 
 */
 
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
+#include "exceptions.h"
 #include "global.h"
 #include "loader.h"
 #include "global.h"
 #include "loader.h"
-#include "main.h"
+#include "options.h"
 #include "native.h"
 #include "tables.h"
 #include "builtin.h"
 #include "native.h"
 #include "tables.h"
 #include "builtin.h"
-#include "jit.h"
+#include "jit/jit.h"
 #include "asmpart.h"
 #include "asmpart.h"
+#include "options.h"
+#include "statistics.h"
 #include "toolbox/memory.h"
 #include "toolbox/memory.h"
-#include "toolbox/loging.h"
+#include "toolbox/logging.h"
 #include "threads/thread.h"
 #include "threads/locks.h"
 #include "threads/thread.h"
 #include "threads/locks.h"
-#include <sys/stat.h>
+#include "nat/java_lang_Throwable.h"
 
 #ifdef USE_ZLIB
 #include "unzip.h"
 
 #ifdef USE_ZLIB
 #include "unzip.h"
 
 /* global variables ***********************************************************/
 
 
 /* global variables ***********************************************************/
 
-int count_class_infos = 0;      /* variables for measurements                 */
-int count_const_pool_len = 0;
-int count_vftbl_len = 0;
-int count_all_methods = 0;
-int count_vmcode_len = 0;
-int count_extable_len = 0;
-int count_class_loads = 0;
-int count_class_inits = 0;
-
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
 static s4 interfaceindex;       /* sequential numbering of interfaces         */
 static s4 classvalue;
 
-list unloadedclasses;       /* list of all referenced but not loaded classes  */
-list unlinkedclasses;       /* list of all loaded but not linked classes      */
-list linkedclasses;         /* list of all completely linked classes          */
-
 
 /* utf-symbols for pointer comparison of frequently used strings */
 
 
 /* utf-symbols for pointer comparison of frequently used strings */
 
-static utf *utf_innerclasses;          /* InnerClasses            */
-static utf *utf_constantvalue;                 /* ConstantValue           */
-static utf *utf_code;                      /* Code                    */
-static utf *utf_exceptions;            /* Exceptions                    */
-static utf *utf_linenumbertable;               /* LineNumberTable                    */
-static utf *utf_finalize;                  /* finalize                */
-static utf *utf_fidesc;                    /* ()V changed             */
-static utf *utf_init;                          /* <init>                  */
-static utf *utf_clinit;                    /* <clinit>                */
-static utf *utf_initsystemclass;       /* initializeSystemClass   */
-static utf *utf_systemclass;           /* java/lang/System        */
-static utf *utf_vmclassloader;      /* java/lang/VMClassLoader */
-static utf *utf_vmclass;            /* java/lang/VMClassLoader */
+static utf *utf_innerclasses;          /* InnerClasses                           */
+static utf *utf_constantvalue;                 /* ConstantValue                          */
+static utf *utf_code;                      /* Code                                   */
+static utf *utf_exceptions;         /* Exceptions                             */
+static utf *utf_linenumbertable;    /* LineNumberTable                        */
+static utf *utf_sourcefile;         /* SourceFile                             */
+static utf *utf_finalize;                  /* finalize                               */
+static utf *utf_fidesc;                    /* ()V changed                            */
+static utf *utf_init;                          /* <init>                                 */
+static utf *utf_clinit;                    /* <clinit>                               */
+static utf *utf_initsystemclass;       /* initializeSystemClass                  */
+static utf *utf_systemclass;           /* java/lang/System                       */
+static utf *utf_vmclassloader;      /* java/lang/VMClassLoader                */
+static utf *utf_vmclass;            /* java/lang/VMClassLoader                */
 static utf *utf_initialize;
 static utf *utf_initializedesc;
 static utf *utf_initialize;
 static utf *utf_initializedesc;
-static utf *utf_java_lang_Object;   /* java/lang/Object        */
-
-
+static utf *utf_java_lang_Object;   /* java/lang/Object                       */
 
 
+utf *utf_fillInStackTrace_name;
+utf *utf_fillInStackTrace_desc;
 
 utf* clinit_desc(){
        return utf_fidesc;
 
 utf* clinit_desc(){
        return utf_fidesc;
@@ -114,8 +107,6 @@ utf* clinit_name(){
 
 classinfo *class_java_lang_Object;
 classinfo *class_java_lang_String;
 
 classinfo *class_java_lang_Object;
 classinfo *class_java_lang_String;
-
-classinfo *class_java_lang_Throwable;
 classinfo *class_java_lang_Cloneable;
 classinfo *class_java_io_Serializable;
 
 classinfo *class_java_lang_Cloneable;
 classinfo *class_java_io_Serializable;
 
@@ -123,24 +114,10 @@ classinfo *class_java_io_Serializable;
 classinfo *pseudo_class_Arraystub = NULL;
 classinfo *pseudo_class_Null = NULL;
 classinfo *pseudo_class_New = NULL;
 classinfo *pseudo_class_Arraystub = NULL;
 classinfo *pseudo_class_Null = NULL;
 classinfo *pseudo_class_New = NULL;
-vftbl *pseudo_class_Arraystub_vftbl = NULL;
-
-/* stefan */
-/* These are made static so they cannot be used for throwing in native */
-/* functions.                                                          */
-static classinfo *class_java_lang_ClassCastException;
-static classinfo *class_java_lang_NullPointerException;
-static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
-static classinfo *class_java_lang_NegativeArraySizeException;
-static classinfo *class_java_lang_OutOfMemoryError;
-static classinfo *class_java_lang_ArithmeticException;
-static classinfo *class_java_lang_ArrayStoreException;
-static classinfo *class_java_lang_ThreadDeath;
+vftbl_t *pseudo_class_Arraystub_vftbl = NULL;
 
 utf *array_packagename = NULL;
 
 
 utf *array_packagename = NULL;
 
-static int loader_inited = 0;
-
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
@@ -175,14 +152,8 @@ primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
 
 /* instances of important system classes **************************************/
 
 
 /* instances of important system classes **************************************/
 
-java_objectheader *proto_java_lang_ClassCastException;
 java_objectheader *proto_java_lang_NullPointerException;
 java_objectheader *proto_java_lang_NullPointerException;
-java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
-java_objectheader *proto_java_lang_NegativeArraySizeException;
-java_objectheader *proto_java_lang_OutOfMemoryError;
-java_objectheader *proto_java_lang_ArithmeticException;
-java_objectheader *proto_java_lang_ArrayStoreException;
-java_objectheader *proto_java_lang_ThreadDeath;
+
 
 /************* functions for reading classdata *********************************
 
 
 /************* functions for reading classdata *********************************
 
@@ -192,103 +163,152 @@ java_objectheader *proto_java_lang_ThreadDeath;
 *******************************************************************************/
 
 static char *classpath    = "";     /* searchpath for classfiles              */
 *******************************************************************************/
 
 static char *classpath    = "";     /* searchpath for classfiles              */
-static u1 *classbuffer    = NULL;   /* pointer to buffer with classfile-data  */
-static u1 *classbuf_pos;            /* current position in classfile buffer   */
-static int classbuffer_size;        /* size of classfile-data                 */
 
 
-/* assert that at least <len> bytes are left to read */
-/* <len> is limited to the range of non-negative s4 values */
-#define ASSERT_LEFT(len)                                                                                               \
-       do {if ( ((s4)(len)) < 0                                                                                        \
-                        || ((classbuffer + classbuffer_size) - classbuf_pos - 1) < (len)) \
-                       panic("Unexpected end of classfile"); } while(0)
 
 
-/* transfer block of classfile data into a buffer */
+/* check_classbuffer_size ******************************************************
+
+   assert that at least <len> bytes are left to read
+   <len> is limited to the range of non-negative s4 values
+
+*******************************************************************************/
+
+static inline bool check_classbuffer_size(classbuffer *cb, s4 len)
+{
+       if (len < 0 || ((cb->data + cb->size) - cb->pos - 1) < len) {
+               *exceptionptr =
+                       new_classformaterror((cb)->class, "Truncated class file");
+
+               return false;
+       }
+
+       return true;
+}
+
+
+/* suck_nbytes *****************************************************************
+
+   transfer block of classfile data into a buffer
+
+*******************************************************************************/
+
+inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+       memcpy(buffer, cb->pos + 1, len);
+       cb->pos += len;
+}
 
 
-#define suck_nbytes(buffer,len)                                                \
-       do {ASSERT_LEFT(len);                                                   \
-               memcpy(buffer,classbuf_pos+1,len);                      \
-               classbuf_pos+=len;} while (0)
 
 
-/* skip block of classfile data */
+/* skip_nbytes ****************************************************************
+
+   skip block of classfile data
+
+*******************************************************************************/
+
+inline void skip_nbytes(classbuffer *cb, s4 len)
+{
+       cb->pos += len;
+}
 
 
-#define skip_nbytes(len)                                               \
-       do {ASSERT_LEFT(len);                                           \
-               classbuf_pos+=len;} while(0)
 
 
-inline u1 suck_u1()
+inline u1 suck_u1(classbuffer *cb)
 {
 {
-       ASSERT_LEFT(1);
-       return *++classbuf_pos;
+       return *++(cb->pos);
 }
 }
-inline u2 suck_u2()
+
+
+inline u2 suck_u2(classbuffer *cb)
 {
 {
-       u1 a=suck_u1(), b=suck_u1();
-       return ((u2)a<<8)+(u2)b;
+       u1 a = suck_u1(cb);
+       u1 b = suck_u1(cb);
+       return ((u2) a << 8) + (u2) b;
 }
 }
-inline u4 suck_u4()
+
+
+inline u4 suck_u4(classbuffer *cb)
 {
 {
-       u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
-       return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
+       u1 a = suck_u1(cb);
+       u1 b = suck_u1(cb);
+       u1 c = suck_u1(cb);
+       u1 d = suck_u1(cb);
+       return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
 }
 }
-#define suck_s8() (s8) suck_u8()
-#define suck_s2() (s2) suck_u2()
-#define suck_s4() (s4) suck_u4()
-#define suck_s1() (s1) suck_u1()
+
+#define suck_s8(a) (s8) suck_u8((a))
+#define suck_s2(a) (s2) suck_u2((a))
+#define suck_s4(a) (s4) suck_u4((a))
+#define suck_s1(a) (s1) suck_u1((a))
 
 
 /* get u8 from classfile data */
 
 
 /* get u8 from classfile data */
-static u8 suck_u8()
+static u8 suck_u8(classbuffer *cb)
 {
 #if U8_AVAILABLE
        u8 lo, hi;
 {
 #if U8_AVAILABLE
        u8 lo, hi;
-       hi = suck_u4();
-       lo = suck_u4();
+       hi = suck_u4(cb);
+       lo = suck_u4(cb);
        return (hi << 32) + lo;
 #else
        u8 v;
        return (hi << 32) + lo;
 #else
        u8 v;
-       v.high = suck_u4();
-       v.low = suck_u4();
+       v.high = suck_u4(cb);
+       v.low = suck_u4(cb);
        return v;
 #endif
 }
 
 
 /* get float from classfile data */
        return v;
 #endif
 }
 
 
 /* get float from classfile data */
-static float suck_float()
+static float suck_float(classbuffer *cb)
 {
        float f;
 
 #if !WORDS_BIGENDIAN 
 {
        float f;
 
 #if !WORDS_BIGENDIAN 
-               u1 buffer[4];
-               u2 i;
-               for (i = 0; i < 4; i++) buffer[3 - i] = suck_u1();
-               memcpy((u1*) (&f), buffer, 4);
-#else 
-               suck_nbytes((u1*) (&f), 4);
+       u1 buffer[4];
+       u2 i;
+
+       for (i = 0; i < 4; i++)
+               buffer[3 - i] = suck_u1(cb);
+
+       memcpy((u1*) (&f), buffer, 4);
+#else
+       suck_nbytes((u1*) (&f), cb, 4);
 #endif
 
 #endif
 
-       PANICIF (sizeof(float) != 4, "Incompatible float-format");
+       if (sizeof(float) != 4) {
+               *exceptionptr = new_exception_message(string_java_lang_InternalError,
+                                                                                         "Incompatible float-format");
+
+               /* XXX should we exit in such a case? */
+               throw_exception_exit();
+       }
        
        return f;
 }
 
 
 /* get double from classfile data */
        
        return f;
 }
 
 
 /* get double from classfile data */
-static double suck_double()
+static double suck_double(classbuffer *cb)
 {
        double d;
 
 #if !WORDS_BIGENDIAN 
 {
        double d;
 
 #if !WORDS_BIGENDIAN 
-               u1 buffer[8];
-               u2 i;   
-               for (i = 0; i < 8; i++) buffer[7 - i] = suck_u1 ();
-               memcpy((u1*) (&d), buffer, 8);
+       u1 buffer[8];
+       u2 i;   
+
+       for (i = 0; i < 8; i++)
+               buffer[7 - i] = suck_u1(cb);
+
+       memcpy((u1*) (&d), buffer, 8);
 #else 
 #else 
-               suck_nbytes((u1*) (&d), 8);
+       suck_nbytes((u1*) (&d), cb, 8);
 #endif
 
 #endif
 
-       PANICIF (sizeof(double) != 8, "Incompatible double-format" );
+       if (sizeof(double) != 8) {
+               *exceptionptr = new_exception_message(string_java_lang_InternalError,
+                                                                                         "Incompatible double-format");
+
+               /* XXX should we exit in such a case? */
+               throw_exception_exit();
+       }
        
        return d;
 }
        
        return d;
 }
@@ -309,114 +329,121 @@ void suck_init(char *cpath)
        int filenamelen;
        union classpath_info *tmp;
        union classpath_info *insertAfter=0;
        int filenamelen;
        union classpath_info *tmp;
        union classpath_info *insertAfter=0;
-       if (!cpath) return;
-       classpath   = cpath;
-       classbuffer = NULL;
-       
-       if (classpath_entries) panic("suck_init should be called only once");
-       for(start=classpath;(*start)!='\0';) {
-               for (end=start; ((*end)!='\0') && ((*end)!=':') ; end++);
-               if (start!=end) {
-                       isZip=0;
-                       filenamelen=(end-start);
-                       if  (filenamelen>3) {
-                               if ( 
-                                       (
-                                               (
-                                                       ((*(end-1))=='p') ||
-                                                       ((*(end-1))=='P')
-                                               ) &&
-                                               (
-                                                       ((*(end-2))=='i') ||
-                                                       ((*(end-2))=='I')
-                                               ) &&
-                                               (
-                                                       ((*(end-3))=='z') ||
-                                                       ((*(end-3))=='Z')
-                                               )
-                                       ) ||
-                                       (
-                                               (
-                                                       ((*(end-1))=='r') ||
-                                                       ((*(end-1))=='R')
-                                               ) &&
-                                               (
-                                                       ((*(end-2))=='a') ||
-                                                       ((*(end-2))=='A')
-                                               ) &&
-                                               (
-                                                       ((*(end-3))=='j') ||
-                                                       ((*(end-3))=='J')
-                                               )
-                                       )
-                               ) isZip=1;
-#if 0
-                               if ( 
-                                       (  (  (*(end - 1)) == 'p') || ( (*(end - 1))  == 'P')) &&
-                                    (((*(end - 2)) == 'i') || ( (*(end - 2)) == 'I'))) &&
-                                        (( (*(end - 3)) == 'z') || ((*(end - 3)) == 'Z'))) 
-                               ) {
-                                       isZip=1;
-                               } else  if ( (( (*(end - 1)) == 'r') || ( (*(end - 1))  == 'R')) &&
-                                    ((*(end - 2)) == 'a') || ( (*(end - 2)) == 'A')) &&
-                                        (( (*(end - 3)) == 'j') || ((*(end - 3)) == 'J')) ) {
-                                       isZip=1;
+
+       if (!cpath)
+               return;
+
+       classpath = cpath;
+       
+       if (classpath_entries)
+               panic("suck_init should be called only once");
+
+       for (start = classpath; (*start) != '\0';) {
+               for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+               if (start != end) {
+                       isZip = 0;
+                       filenamelen = end - start;
+
+                       if (filenamelen > 3) {
+                               if (strncasecmp(end - 3, "zip", 3) == 0 ||
+                                       strncasecmp(end - 3, "jar", 3) == 0) {
+                                       isZip = 1;
                                }
                                }
-#endif
                        }
                        }
-                       if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init"); 
+
+                       if (filenamelen >= (CLASSPATH_MAXFILENAME - 1))
+                               panic("path length >= MAXFILENAME in suck_init");
+
                        if (!filename)
                        if (!filename)
-                               filename=(char*)malloc(CLASSPATH_MAXFILENAME);
-                       strncpy(filename,start,filenamelen);
-                       filename[filenamelen+1]='\0';
-                       tmp=0;
+                               filename = MNEW(char, CLASSPATH_MAXFILENAME);
+
+                       strncpy(filename, start, filenamelen);
+                       filename[filenamelen + 1] = '\0';
+                       tmp = NULL;
 
                        if (isZip) {
 
                        if (isZip) {
-#ifdef USE_ZLIB
-                               unzFile uf=unzOpen(filename);
+#if defined(USE_ZLIB)
+                               unzFile uf = unzOpen(filename);
+
                                if (uf) {
                                if (uf) {
-                                       tmp=(union classpath_info*)malloc(sizeof(classpath_info));
-                                       tmp->archive.type=CLASSPATH_ARCHIVE;
-                                       tmp->archive.uf=uf;
-                                       tmp->archive.next=0;
-                                       filename=0;
+                                       tmp = (union classpath_info *) NEW(classpath_info);
+                                       tmp->archive.type = CLASSPATH_ARCHIVE;
+                                       tmp->archive.uf = uf;
+                                       tmp->archive.next = NULL;
+                                       filename = NULL;
                                }
 #else
                                }
 #else
-                               panic("Zip/JAR not supported");
+                               throw_cacao_exception_exit(string_java_lang_InternalError, "zip/jar files not supported");
 #endif
                                
                        } else {
 #endif
                                
                        } else {
-                               tmp=(union classpath_info*)malloc(sizeof(classpath_info));
-                               tmp->filepath.type=CLASSPATH_PATH;
-                               tmp->filepath.next=0;
-                               if (filename[filenamelen-1]!='/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
-                                       filename[filenamelen]='/';
-                                       filename[filenamelen+1]='\0';
+                               tmp = (union classpath_info *) NEW(classpath_info);
+                               tmp->filepath.type = CLASSPATH_PATH;
+                               tmp->filepath.next = 0;
+
+                               if (filename[filenamelen - 1] != '/') {/*PERHAPS THIS SHOULD BE READ FROM A GLOBAL CONFIGURATION */
+                                       filename[filenamelen] = '/';
+                                       filename[filenamelen + 1] = '\0';
                                        filenamelen++;
                                }
                        
                                        filenamelen++;
                                }
                        
-                               tmp->filepath.filename=filename;
-                               tmp->filepath.pathlen=filenamelen;                              
-                               filename=0;
+                               tmp->filepath.filename = filename;
+                               tmp->filepath.pathlen = filenamelen;                            
+                               filename = NULL;
                        }
 
                        }
 
-               if (tmp) {
-                       if (insertAfter) {
-                               insertAfter->filepath.next=tmp;
-                       } else {
-                               classpath_entries=tmp;  
+                       if (tmp) {
+                               if (insertAfter) {
+                                       insertAfter->filepath.next = tmp;
+
+                               } else {
+                                       classpath_entries = tmp;
+                               }
+                               insertAfter = tmp;
                        }
                        }
-                       insertAfter=tmp;
                }
                }
-       }
-               if ((*end)==':') start=end+1; else start=end;
-       
+
+               if ((*end) == ':')
+                       start = end + 1;
+               else
+                       start = end;
        
        
-       if (filename!=0) free(filename);
+               if (filename) {
+                       MFREE(filename, char, CLASSPATH_MAXFILENAME);
+                       filename = NULL;
+               }
+       }
 }
 
 }
 
+
+void create_all_classes()
+{
+       classpath_info *cpi;
+
+       for (cpi = classpath_entries; cpi != 0; cpi = cpi->filepath.next) {
+#if defined(USE_ZLIB)
+               if (cpi->filepath.type == CLASSPATH_ARCHIVE) {
+                       cacao_entry_s *ce;
+                       unz_s *s;
+
+                       s = (unz_s *) cpi->archive.uf;
+                       ce = s->cacao_dir_list;
+                               
+                       while (ce) {
+                               (void) class_new(ce->name);
+                               ce = ce->next;
+                       }
+
+               } else {
+#endif
+#if defined(USE_ZLIB)
+               }
+#endif
+       }
 }
 
 }
 
+
 /************************** function suck_start ********************************
 
        returns true if classbuffer is already loaded or a file for the
 /************************** function suck_start ********************************
 
        returns true if classbuffer is already loaded or a file for the
@@ -426,47 +453,61 @@ void suck_init(char *cpath)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-bool suck_start(utf *classname)
+classbuffer *suck_start(classinfo *c)
 {
        classpath_info *currPos;
        char *utf_ptr;
 {
        classpath_info *currPos;
        char *utf_ptr;
-       char c;
-       char filename[CLASSPATH_MAXFILENAME+10];  /* room for '.class'                      */  
+       char ch;
+       char filename[CLASSPATH_MAXFILENAME+10];  /* room for '.class'            */
        int  filenamelen=0;
        FILE *classfile;
        int  err;
        struct stat buffer;
        int  filenamelen=0;
        FILE *classfile;
        int  err;
        struct stat buffer;
+       classbuffer *cb;
 
 
-       if (classbuffer) return true; /* classbuffer is already valid */
+       utf_ptr = c->name->text;
 
 
-       utf_ptr = classname->text;
-       while (utf_ptr < utf_end(classname)) {
-               PANICIF (filenamelen >= CLASSPATH_MAXFILENAME, "Filename too long");
-               c = *utf_ptr++;
-               if ((c <= ' ' || c > 'z') && (c != '/'))     /* invalid character */
-                       c = '?';
-               filename[filenamelen++] = c;
+       while (utf_ptr < utf_end(c->name)) {
+               if (filenamelen >= CLASSPATH_MAXFILENAME) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_InternalError,
+                                                                         "Filename too long");
+
+                       /* XXX should we exit in such a case? */
+                       throw_exception_exit();
+               }
+
+               ch = *utf_ptr++;
+               if ((ch <= ' ' || ch > 'z') && (ch != '/'))     /* invalid character */
+                       ch = '?';
+               filename[filenamelen++] = ch;
        }
        }
+
        strcpy(filename + filenamelen, ".class");
        strcpy(filename + filenamelen, ".class");
-       filenamelen+=6;
-       for (currPos=classpath_entries;currPos!=0;currPos=currPos->filepath.next) {
-#ifdef USE_ZLIB
-               if (currPos->filepath.type==CLASSPATH_ARCHIVE) {
-                       if (cacao_locate(currPos->archive.uf,classname) == UNZ_OK) {
+       filenamelen += 6;
+
+       for (currPos = classpath_entries; currPos != 0; currPos = currPos->filepath.next) {
+#if defined(USE_ZLIB)
+               if (currPos->filepath.type == CLASSPATH_ARCHIVE) {
+                       if (cacao_locate(currPos->archive.uf, c->name) == UNZ_OK) {
                                unz_file_info file_info;
                                /*log_text("Class found in zip file");*/
                                if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
                                                sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
                                        if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
                                unz_file_info file_info;
                                /*log_text("Class found in zip file");*/
                                if (unzGetCurrentFileInfo(currPos->archive.uf, &file_info, filename,
                                                sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
                                        if (unzOpenCurrentFile(currPos->archive.uf) == UNZ_OK) {
-                                               classbuffer_size = file_info.uncompressed_size;                         
-                                               classbuffer      = MNEW(u1, classbuffer_size);
-                                               classbuf_pos     = classbuffer - 1;
+                                               cb = NEW(classbuffer);
+                                               cb->class = c;
+                                               cb->size = file_info.uncompressed_size;
+                                               cb->data = MNEW(u1, cb->size);
+                                               cb->pos = cb->data - 1;
                                                /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
                                                /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
-                                               if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
+                                               if (unzReadCurrentFile(currPos->archive.uf, cb->data, cb->size) == cb->size) {
                                                        unzCloseCurrentFile(currPos->archive.uf);
                                                        unzCloseCurrentFile(currPos->archive.uf);
-                                                       return true;
+                                                       return cb;
+
                                                } else {
                                                } else {
-                                                       MFREE(classbuffer, u1, classbuffer_size);
+                                                       MFREE(cb->data, u1, cb->size);
+                                                       FREE(cb, classbuffer);
                                                        log_text("Error while unzipping");
                                                }
                                        } else log_text("Error while opening file in archive");
                                                        log_text("Error while unzipping");
                                                }
                                        } else log_text("Error while opening file in archive");
@@ -476,27 +517,29 @@ bool suck_start(utf *classname)
 
                } else {
 #endif
 
                } else {
 #endif
-                       if ((currPos->filepath.pathlen+filenamelen)>=CLASSPATH_MAXFILENAME) continue;
-                       strcpy(currPos->filepath.filename+currPos->filepath.pathlen,filename);
+                       if ((currPos->filepath.pathlen + filenamelen) >= CLASSPATH_MAXFILENAME) continue;
+                       strcpy(currPos->filepath.filename + currPos->filepath.pathlen, filename);
                        classfile = fopen(currPos->filepath.filename, "r");
                        if (classfile) {                                       /* file exists */
 
                                /* determine size of classfile */
 
                                /* dolog("File: %s",filename); */
                        classfile = fopen(currPos->filepath.filename, "r");
                        if (classfile) {                                       /* file exists */
 
                                /* determine size of classfile */
 
                                /* dolog("File: %s",filename); */
-
                                err = stat(currPos->filepath.filename, &buffer);
 
                                err = stat(currPos->filepath.filename, &buffer);
 
-                               if (!err) {                                /* read classfile data */                            
-                                       classbuffer_size = buffer.st_size;                              
-                                       classbuffer      = MNEW(u1, classbuffer_size);
-                                       classbuf_pos     = classbuffer - 1;
-                                       fread(classbuffer, 1, classbuffer_size, classfile);
+                               if (!err) {                            /* 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;
+                                       fread(cb->data, 1, cb->size, classfile);
                                        fclose(classfile);
                                        fclose(classfile);
-                                       return true;
+
+                                       return cb;
                                }
                        }
                                }
                        }
-#ifdef USE_ZLIB
+#if defined(USE_ZLIB)
                }
 #endif
        }
                }
 #endif
        }
@@ -505,10 +548,10 @@ bool suck_start(utf *classname)
                dolog("Warning: Can not open class file '%s'", filename);
        }
 
                dolog("Warning: Can not open class file '%s'", filename);
        }
 
-       return false;
-
+       return NULL;
 }
 
 }
 
+
 /************************** function suck_stop *********************************
 
        frees memory for buffer with classfile data.
 /************************** function suck_stop *********************************
 
        frees memory for buffer with classfile data.
@@ -517,24 +560,12 @@ bool suck_start(utf *classname)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-void suck_stop()
+void suck_stop(classbuffer *cb)
 {
 {
-       /* determine amount of classdata not retrieved by suck-operations         */
-
-       int classdata_left = ((classbuffer + classbuffer_size) - classbuf_pos - 1);
-
-       if (classdata_left > 0) {
-               /* surplus */           
-               dolog("There are %d extra bytes at end of classfile",
-                               classdata_left);
-               /* The JVM spec disallows extra bytes. */
-               panic("Extra bytes at end of classfile");
-       }
-
        /* free memory */
 
        /* free memory */
 
-       MFREE(classbuffer, u1, classbuffer_size);
-       classbuffer = NULL;
+       MFREE(cb->data, u1, cb->size);
+       FREE(cb, classbuffer);
 }
 
 
 }
 
 
@@ -576,21 +607,6 @@ void printflags(u2 f)
 }
 
 
 }
 
 
-/************************* Function: skipattribute *****************************
-
-       skips a (1) 'attribute' structure in the class file
-
-*******************************************************************************/
-
-static void skipattribute()
-{
-       u4 len;
-       suck_u2 ();
-       len = suck_u4();
-       skip_nbytes(len);       
-}
-
-
 /********************** Function: skipattributebody ****************************
 
        skips an attribute after the 16 bit reference to attribute_name has already
 /********************** Function: skipattributebody ****************************
 
        skips an attribute after the 16 bit reference to attribute_name has already
@@ -598,11 +614,21 @@ static void skipattribute()
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void skipattributebody()
+static bool skipattributebody(classbuffer *cb)
 {
        u4 len;
 {
        u4 len;
-       len = suck_u4();
-       skip_nbytes(len);
+
+       if (!check_classbuffer_size(cb, 4))
+               return false;
+
+       len = suck_u4(cb);
+
+       if (!check_classbuffer_size(cb, len))
+               return false;
+
+       skip_nbytes(cb, len);
+
+       return true;
 }
 
 
 }
 
 
@@ -612,17 +638,31 @@ static void skipattributebody()
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void skipattributes(u4 num)
+static bool skipattributes(classbuffer *cb, u4 num)
 {
        u4 i;
 {
        u4 i;
-       for (i = 0; i < num; i++)
-               skipattribute();
+       u4 len;
+
+       for (i = 0; i < num; i++) {
+               if (!check_classbuffer_size(cb, 2 + 4))
+                       return false;
+
+               suck_u2(cb);
+               len = suck_u4(cb);
+
+               if (!check_classbuffer_size(cb, len))
+                       return false;
+
+               skip_nbytes(cb, len);
+       }
+
+       return true;
 }
 
 
 /******************** function: innerclass_getconstant ************************
 
 }
 
 
 /******************** function: innerclass_getconstant ************************
 
-    like class_getconstant, but if cptags is ZERO null is returned                                      
+    like class_getconstant, but if cptags is ZERO null is returned
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
@@ -652,46 +692,72 @@ voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void attribute_load(u4 num, classinfo *c)
+static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
 {
        u4 i, j;
 
        for (i = 0; i < num; i++) {
 {
        u4 i, j;
 
        for (i = 0; i < num; i++) {
+               utf *aname;
+
                /* retrieve attribute name */
                /* retrieve attribute name */
-               utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
+
+               aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
 
                if (aname == utf_innerclasses) {
                        /* innerclasses attribute */
 
                if (aname == utf_innerclasses) {
                        /* innerclasses attribute */
-
                        if (c->innerclass != NULL)
                                panic("Class has more than one InnerClasses attribute");
                                
                        if (c->innerclass != NULL)
                                panic("Class has more than one InnerClasses attribute");
                                
+                       if (!check_classbuffer_size(cb, 4 + 2))
+                               return false;
+
                        /* skip attribute length */                                             
                        /* skip attribute length */                                             
-                       suck_u4(); 
+                       suck_u4(cb);
+
                        /* number of records */
                        /* number of records */
-                       c->innerclasscount = suck_u2();
+                       c->innerclasscount = suck_u2(cb);
+
+                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+                               return false;
+
                        /* allocate memory for innerclass structure */
                        c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
 
                        for (j = 0; j < c->innerclasscount; j++) {
                        /* allocate memory for innerclass structure */
                        c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
 
                        for (j = 0; j < c->innerclasscount; j++) {
-                               /*  The innerclass structure contains a class with an encoded name, 
-                                   its defining scope, its simple name  and a bitmask of the access flags. 
-                                   If an inner class is not a member, its outer_class is NULL, 
-                                   if a class is anonymous, its name is NULL.                              */
+                               /* The innerclass structure contains a class with an encoded
+                                  name, its defining scope, its simple name  and a bitmask of
+                                  the access flags. If an inner class is not a member, its
+                                  outer_class is NULL, if a class is anonymous, its name is
+                                  NULL. */
                                                                
                                innerclassinfo *info = c->innerclass + j;
 
                                                                
                                innerclassinfo *info = c->innerclass + j;
 
-                               info->inner_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
-                               info->outer_class = innerclass_getconstant(c, suck_u2(), CONSTANT_Class); /* CONSTANT_Class_info index */
-                               info->name  = innerclass_getconstant(c, suck_u2(), CONSTANT_Utf8);        /* CONSTANT_Utf8_info index  */
-                               info->flags = suck_u2();                                                  /* access_flags bitmask      */
+                               info->inner_class =
+                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               info->outer_class =
+                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               info->name =
+                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+                               info->flags = suck_u2(cb);
                        }
 
                        }
 
+               } else if (aname == utf_sourcefile) {
+                       if (!check_classbuffer_size(cb, 4 + 2))
+                               return false;
+
+                       suck_u4(cb);
+                       c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+
                } else {
                        /* unknown attribute */
                } else {
                        /* unknown attribute */
-                       skipattributebody();
+                       if (!skipattributebody(cb))
+                               return false;
                }
        }
                }
        }
+
+       return true;
 }
 
 
 }
 
 
@@ -754,14 +820,18 @@ static void checkfielddescriptor (char *utf_ptr, char *end_pos)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static int checkmethoddescriptor (utf *d)
+static int checkmethoddescriptor(classinfo *c, utf *descriptor)
 {
 {
-       char *utf_ptr = d->text;     /* current position in utf text   */
-       char *end_pos = utf_end(d);  /* points behind utf string       */
-       int argcount = 0;            /* number of arguments            */
+       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 */
 
        /* method descriptor must start with parenthesis */
-       if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+       if (utf_ptr == end_pos || *utf_ptr++ != '(')
+               panic ("Missing '(' in method descriptor");
 
     /* check arguments */
     while (utf_ptr != end_pos && *utf_ptr != ')') {
 
     /* check arguments */
     while (utf_ptr != end_pos && *utf_ptr != ')') {
@@ -777,16 +847,24 @@ static int checkmethoddescriptor (utf *d)
                                                          | CLASSLOAD_NOVOID);
        }
 
                                                          | CLASSLOAD_NOVOID);
        }
 
-       if (utf_ptr == end_pos) panic("Missing ')' in method descriptor");
+       if (utf_ptr == end_pos)
+               panic("Missing ')' in method descriptor");
+
     utf_ptr++; /* skip ')' */
 
     utf_ptr++; /* skip ')' */
 
-       class_from_descriptor(utf_ptr,end_pos,NULL,
-                                                 CLASSLOAD_NEW
-                                                 | CLASSLOAD_NULLPRIMITIVE
-                                                 | CLASSLOAD_CHECKEND);
+       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 (argcount > 255)
-               panic("Invalid method descriptor: too many arguments");
+               return 0;
+       }
 
        return argcount;
 
 
        return argcount;
 
@@ -873,25 +951,28 @@ void print_arraydescriptor(FILE *file, arraydescriptor *desc)
 /******************************************************************************/
 
 
 /******************************************************************************/
 
 
-/************************ Function: field_load *********************************
+/* field_load ******************************************************************
 
 
-       Load everything about a class field from the class file and fill a
-       'fieldinfo' structure. For static fields, space in the data segment is
-       allocated.
+   Load everything about a class field from the class file and fill a
+   'fieldinfo' structure. For static fields, space in the data segment is
+   allocated.
 
 *******************************************************************************/
 
 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
 
 
 *******************************************************************************/
 
 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
 
-static void field_load(fieldinfo *f, classinfo *c)
+static bool field_load(classbuffer *cb, classinfo *c, fieldinfo *f)
 {
        u4 attrnum,i;
        u4 jtype;
 {
        u4 attrnum,i;
        u4 jtype;
-       u4 pindex = field_load_NOVALUE;                               /* constantvalue_index */
+       u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
+
+       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+               return false;
 
 
-       f->flags = suck_u2();                                           /* ACC flags         */
-       f->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);       /* name of field     */
-       f->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8); /* JavaVM descriptor */
+       f->flags = suck_u2(cb);
+       f->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+       f->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
        
        if (opt_verify) {
                /* check name */
        
        if (opt_verify) {
                /* check name */
@@ -900,32 +981,36 @@ static void field_load(fieldinfo *f, classinfo *c)
                
                /* check flag consistency */
                i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
                
                /* check flag consistency */
                i = (f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
+
                if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
                        panic("Field has invalid access flags");
                if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
                        panic("Field has invalid access flags");
+
                if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
                        panic("Field is declared final and volatile");
                if ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))
                        panic("Field is declared final and volatile");
+
                if ((c->flags & ACC_INTERFACE) != 0) {
                        if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
                                != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
                                panic("Interface field is not declared static final public");
                if ((c->flags & ACC_INTERFACE) != 0) {
                        if ((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
                                != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
                                panic("Interface field is not declared static final public");
+
                        if ((f->flags & ACC_TRANSIENT) != 0)
                                panic("Interface field declared transient");
                }
 
                /* check descriptor */
                        if ((f->flags & ACC_TRANSIENT) != 0)
                                panic("Interface field declared transient");
                }
 
                /* check descriptor */
-               checkfielddescriptor(f->descriptor->text,utf_end(f->descriptor));
+               checkfielddescriptor(f->descriptor->text, utf_end(f->descriptor));
        }
                
        }
                
-       f->type = jtype = desc_to_type(f->descriptor);                      /* data type         */
-       f->offset = 0;                                                            /* offset from start of object */
+       f->type = jtype = desc_to_type(f->descriptor);    /* data type            */
+       f->offset = 0;                             /* offset from start of object */
        f->class = c;
        f->xta = NULL;
        
        switch (f->type) {
        f->class = c;
        f->xta = NULL;
        
        switch (f->type) {
-       case TYPE_INT:        f->value.i = 0; break;
-       case TYPE_FLOAT:      f->value.f = 0.0; break;
-       case TYPE_DOUBLE:     f->value.d = 0.0; break;
-       case TYPE_ADDRESS:    f->value.a = NULL; break;
+       case TYPE_INT:     f->value.i = 0; break;
+       case TYPE_FLOAT:   f->value.f = 0.0; break;
+       case TYPE_DOUBLE:  f->value.d = 0.0; break;
+       case TYPE_ADDRESS: f->value.a = NULL; break;
        case TYPE_LONG:
 #if U8_AVAILABLE
                f->value.l = 0; break;
        case TYPE_LONG:
 #if U8_AVAILABLE
                f->value.l = 0; break;
@@ -935,28 +1020,37 @@ static void field_load(fieldinfo *f, classinfo *c)
        }
 
        /* read attributes */
        }
 
        /* read attributes */
-       attrnum = suck_u2();
+       if (!check_classbuffer_size(cb, 2))
+               return false;
+
+       attrnum = suck_u2(cb);
        for (i = 0; i < attrnum; i++) {
                utf *aname;
 
        for (i = 0; i < attrnum; i++) {
                utf *aname;
 
-               aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
+
+               aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
                
                if (aname != utf_constantvalue) {
                        /* unknown attribute */
                
                if (aname != utf_constantvalue) {
                        /* unknown attribute */
-                       skipattributebody();
+                       if (!skipattributebody(cb))
+                               return false;
 
                } else {
                        /* constant value attribute */
 
                } else {
                        /* constant value attribute */
-
                        if (pindex != field_load_NOVALUE)
                                panic("Field has more than one ConstantValue attribute");
                        
                        if (pindex != field_load_NOVALUE)
                                panic("Field has more than one ConstantValue attribute");
                        
+                       if (!check_classbuffer_size(cb, 4 + 2))
+                               return false;
+
                        /* check attribute length */
                        /* check attribute length */
-                       if (suck_u4() != 2)
+                       if (suck_u4(cb) != 2)
                                panic("ConstantValue attribute has invalid length");
                        
                        /* index of value in constantpool */            
                                panic("ConstantValue attribute has invalid length");
                        
                        /* index of value in constantpool */            
-                       pindex = suck_u2();
+                       pindex = suck_u2(cb);
                
                        /* initialize field with value from constantpool */             
                        switch (jtype) {
                
                        /* initialize field with value from constantpool */             
                        switch (jtype) {
@@ -1000,12 +1094,16 @@ static void field_load(fieldinfo *f, classinfo *c)
                        }
                }
        }
                        }
                }
        }
+
+       /* everything was ok */
+
+       return true;
 }
 
 
 /********************** function: field_free **********************************/
 
 }
 
 
 /********************** function: field_free **********************************/
 
-static void field_free (fieldinfo *f)
+static void field_free(fieldinfo *f)
 {
        /* empty */
 }
 {
        /* empty */
 }
@@ -1026,67 +1124,87 @@ void field_display(fieldinfo *f)
 
 
 /******************************************************************************/
 
 
 /******************************************************************************/
-/************************* Functions for methods ******************************/ 
+/************************* Functions for methods ******************************/
 /******************************************************************************/
 
 
 /******************************************************************************/
 
 
-/*********************** Function: method_load *********************************
+/* method_load *****************************************************************
 
 
-       Loads a method from the class file and fills an existing 'methodinfo'
-       structure. For native methods, the function pointer field is set to the
-       real function pointer, for JavaVM methods a pointer to the compiler is used
-       preliminarily.
+   Loads a method from the class file and fills an existing 'methodinfo'
+   structure. For native methods, the function pointer field is set to the
+   real function pointer, for JavaVM methods a pointer to the compiler is used
+   preliminarily.
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void method_load(methodinfo *m, classinfo *c)
+static bool method_load(classbuffer *cb, classinfo *c, methodinfo *m)
 {
 {
-       u4 attrnum, i, e;
-       int argcount;
-       
+       s4 argcount;
+       s4 i, j;
+       u4 attrnum;
+       u4 codeattrnum;
+
 #ifdef STATISTICS
 #ifdef STATISTICS
-       count_all_methods++;
+       if (opt_stat)
+               count_all_methods++;
 #endif
 #endif
-       m->thrownexceptionscount=0;
-       m->linenumbercount=0;
-       m->linenumbers=0;
+
+       m->thrownexceptionscount = 0;
+       m->linenumbercount = 0;
+       m->linenumbers = 0;
        m->class = c;
        m->class = c;
+       m->nativelyoverloaded = false;
        
        
-       m->flags = suck_u2();
-       m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+               return false;
+
+       m->flags = suck_u2(cb);
+       m->name = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+       m->descriptor = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
 
        if (opt_verify) {
                if (!is_valid_name_utf(m->name))
                        panic("Method with invalid name");
 
        if (opt_verify) {
                if (!is_valid_name_utf(m->name))
                        panic("Method with invalid name");
+
                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)
                        panic("Method with invalid special name");
        }
        
-       m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
-       argcount = checkmethoddescriptor(m->descriptor);
-       if ((m->flags & ACC_STATIC) == 0)
+       argcount = checkmethoddescriptor(c, m->descriptor);
+
+       if (!(m->flags & ACC_STATIC))
                argcount++; /* count the 'this' argument */
 
        if (opt_verify) {
                if (argcount > 255)
                argcount++; /* count the 'this' argument */
 
        if (opt_verify) {
                if (argcount > 255)
-                       panic("Method has more than 255 arguments");
+                       panic("Too many arguments in signature");
 
                /* check flag consistency */
                if (m->name != utf_clinit) {
                        i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
 
                /* check flag consistency */
                if (m->name != utf_clinit) {
                        i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
+
                        if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
                                panic("Method has invalid access flags");
                        if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED)
                                panic("Method has invalid access flags");
+
                        if ((m->flags & ACC_ABSTRACT) != 0) {
                        if ((m->flags & ACC_ABSTRACT) != 0) {
-                               if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE | ACC_STATIC
-                                                                | ACC_STRICT | ACC_SYNCHRONIZED)) != 0)
-                                       panic("Abstract method has invalid flags set");
+                               if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
+                                                                ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Illegal method modifiers: 0x%x",
+                                                                                        m->flags);
+
+                                       return false;
+                               }
                        }
                        }
+
                        if ((c->flags & ACC_INTERFACE) != 0) {
                                if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
                                        != (ACC_ABSTRACT | ACC_PUBLIC))
                                        panic("Interface method is not declared abstract and public");
                        }
                        if ((c->flags & ACC_INTERFACE) != 0) {
                                if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
                                        != (ACC_ABSTRACT | ACC_PUBLIC))
                                        panic("Interface method is not declared abstract and public");
                        }
+
                        if (m->name == utf_init) {
                                if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
                                                                 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
                        if (m->name == utf_init) {
                                if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
                                                                 | ACC_NATIVE | ACC_ABSTRACT)) != 0)
@@ -1096,10 +1214,18 @@ static void method_load(methodinfo *m, classinfo *c)
        }
                
        m->jcode = NULL;
        }
                
        m->jcode = NULL;
+       m->basicblockcount = 0;
+       m->basicblocks = NULL;
+       m->basicblockindex = NULL;
+       m->instructioncount = 0;
+       m->instructions = NULL;
+       m->stackcount = 0;
+       m->stack = NULL;
        m->exceptiontable = NULL;
        m->exceptiontable = NULL;
-       m->entrypoint = NULL;
-       m->mcode = NULL;
+       m->registerdata = NULL;
        m->stubroutine = NULL;
        m->stubroutine = NULL;
+       m->mcode = NULL;
+       m->entrypoint = NULL;
        m->methodUsed = NOTUSED;    
        m->monoPoly = MONO;    
        m->subRedefs = 0;
        m->methodUsed = NOTUSED;    
        m->monoPoly = MONO;    
        m->subRedefs = 0;
@@ -1118,101 +1244,187 @@ static void method_load(methodinfo *m, classinfo *c)
                }
        }
        
                }
        }
        
+       if (!check_classbuffer_size(cb, 2))
+               return false;
        
        
-       attrnum = suck_u2();
+       attrnum = suck_u2(cb);
        for (i = 0; i < attrnum; i++) {
                utf *aname;
 
        for (i = 0; i < attrnum; i++) {
                utf *aname;
 
-               aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
+
+               aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
 
                if (aname != utf_code) {
                        if (aname == utf_exceptions) {
 
                if (aname != utf_code) {
                        if (aname == utf_exceptions) {
-                               u2 exceptionCount;
-                               u2 exceptionID;
-                               suck_u4(); /*length*/
-                               exceptionCount=suck_u2();
-                               m->thrownexceptionscount=exceptionCount;
-                               m->thrownexceptions=MNEW(classinfo*,exceptionCount);
-                               for (exceptionID=0;exceptionID<exceptionCount;exceptionID++) {
-                                       (m->thrownexceptions)[exceptionID]=class_getconstant(c,suck_u2(),CONSTANT_Class);
+                               s4 j;
+                               
+                               if (!check_classbuffer_size(cb, 4 + 2))
+                                       return false;
+
+                               suck_u4(cb); /*length*/
+                               m->thrownexceptionscount = suck_u2(cb);
+
+                               if (!check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
+                                       return false;
+
+                               m->thrownexceptions = MNEW(classinfo*, m->thrownexceptionscount);
+
+                               for (j = 0; j < m->thrownexceptionscount; j++) {
+                                       (m->thrownexceptions)[j] =
+                                               class_getconstant(c, suck_u2(cb), CONSTANT_Class);
                                }
                                }
+                               
+                       } else {
+                               if (!skipattributebody(cb))
+                                       return false;
                        }
                        }
-                       else
-                       skipattributebody();
 
                } else {
 
                } else {
-                       u4 codelen;
-                       if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
-                               panic("Code attribute for native or abstract method");
+                       if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Code attribute in native or abstract methods");
+
+                                       return false;
+                       }
+                       
+                       if (m->jcode) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple Code attributes");
+
+                               return false;
+                       }
+
+                       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+                               return false;
+
+                       suck_u4(cb);
+                       m->maxstack = suck_u2(cb);
+                       m->maxlocals = suck_u2(cb);
+
+                       if (m->maxlocals < argcount) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Arguments can't fit into locals");
+
+                               return false;
+                       }
                        
                        
-                       if (m->jcode)
-                               panic("Method has more than one Code attribute");
-
-                       suck_u4();
-                       m->maxstack = suck_u2();
-                       m->maxlocals = suck_u2();
-                       if (m->maxlocals < argcount)
-                               panic("max_locals is smaller than the number of arguments");
+                       if (!check_classbuffer_size(cb, 4))
+                               return false;
+
+                       m->jcodelength = suck_u4(cb);
+
+                       if (m->jcodelength == 0) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Code of a method has length 0");
+
+                               return false;
+                       }
                        
                        
-                       codelen = suck_u4();
-                       if (codelen == 0)
-                               panic("bytecode has zero length");
-                       if (codelen > 65536)
-                               panic("bytecode too long");
-                       m->jcodelength = codelen;
+                       if (m->jcodelength > 65535) {
+                               *exceptionptr =
+                                       new_classformaterror(c,
+                                                                                "Code of a method longer than 65535 bytes");
+
+                               return false;
+                       }
+
+                       if (!check_classbuffer_size(cb, m->jcodelength))
+                               return false;
+
                        m->jcode = MNEW(u1, m->jcodelength);
                        m->jcode = MNEW(u1, m->jcodelength);
-                       suck_nbytes(m->jcode, m->jcodelength);
-                       m->exceptiontablelength = suck_u2();
-                       m->exceptiontable = 
-                               MNEW(exceptiontable, m->exceptiontablelength);
+                       suck_nbytes(m->jcode, cb, m->jcodelength);
 
 
-#ifdef STATISTICS
-                       count_vmcode_len += m->jcodelength + 18;
-                       count_extable_len += 8 * m->exceptiontablelength;
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       m->exceptiontablelength = suck_u2(cb);
+
+                       if (!check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->exceptiontablelength))
+                               return false;
+
+                       m->exceptiontable = MNEW(exceptiontable, m->exceptiontablelength);
+
+#if defined(STATISTICS)
+                       if (opt_stat) {
+                               count_vmcode_len += m->jcodelength + 18;
+                               count_extable_len += 8 * m->exceptiontablelength;
+                       }
 #endif
 
 #endif
 
-                       for (e = 0; e < m->exceptiontablelength; e++) {
+                       for (j = 0; j < m->exceptiontablelength; j++) {
                                u4 idx;
                                u4 idx;
-                               m->exceptiontable[e].startpc = suck_u2();
-                               m->exceptiontable[e].endpc = suck_u2();
-                               m->exceptiontable[e].handlerpc = suck_u2();
+                               m->exceptiontable[j].startpc = suck_u2(cb);
+                               m->exceptiontable[j].endpc = suck_u2(cb);
+                               m->exceptiontable[j].handlerpc = suck_u2(cb);
 
 
-                               idx = suck_u2();
+                               idx = suck_u2(cb);
                                if (!idx) {
                                if (!idx) {
-                                       m->exceptiontable[e].catchtype = NULL;
+                                       m->exceptiontable[j].catchtype = NULL;
 
                                } else {
 
                                } else {
-                                       m->exceptiontable[e].catchtype = 
-                                     class_getconstant(c, idx, CONSTANT_Class);
+                                       m->exceptiontable[j].catchtype =
+                                               class_getconstant(c, idx, CONSTANT_Class);
                                }
                                }
-                       }                       
-                       {
-                               u2 codeattrnum;
-                               for (codeattrnum=suck_u2();codeattrnum>0;codeattrnum--) {
-                                       utf * caname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
-                                       if (caname==utf_linenumbertable) {
-                                               u2 lncid;
-                                               /*log_text("LineNumberTable found");*/
-                                               suck_u4();
-                                               m->linenumbercount=suck_u2();
-                                               /*printf("length:%d\n",m->linenumbercount);*/
-                                               m->linenumbers=MNEW(lineinfo,m->linenumbercount);
-                                               for (lncid=0;lncid<m->linenumbercount;lncid++) {
-                                                       m->linenumbers[lncid].start_pc=suck_u2();
-                                                       m->linenumbers[lncid].line_number=suck_u2();
-                                               }
-                                               codeattrnum--;
-                                               skipattributes(codeattrnum);
-                                               break;
-                                       } else skipattributebody();
+                       }
+
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       codeattrnum = suck_u2(cb);
+
+                       for (; codeattrnum > 0; codeattrnum--) {
+                               utf *caname;
+
+                               if (!check_classbuffer_size(cb, 2))
+                                       return false;
+
+                               caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+
+                               if (caname == utf_linenumbertable) {
+                                       u2 lncid;
+
+                                       if (!check_classbuffer_size(cb, 4 + 2))
+                                               return false;
+
+                                       suck_u4(cb);
+                                       m->linenumbercount = suck_u2(cb);
+
+                                       if (!check_classbuffer_size(cb,
+                                                                                               (2 + 2) * m->linenumbercount))
+                                               return false;
+
+                                       m->linenumbers = MNEW(lineinfo, m->linenumbercount);
                                        
                                        
-                               }                               
+                                       for (lncid = 0; lncid < m->linenumbercount; lncid++) {
+                                               m->linenumbers[lncid].start_pc = suck_u2(cb);
+                                               m->linenumbers[lncid].line_number = suck_u2(cb);
+                                       }
+                                       codeattrnum--;
+
+                                       if (!skipattributes(cb, codeattrnum))
+                                               return false;
+                                       
+                                       break;
+                               } else {
+                                       if (!skipattributebody(cb))
+                                               return false;
+                               }
                        }
                }
        }
 
                        }
                }
        }
 
-       if (!m->jcode && (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) == 0)
-               panic("Method missing Code attribute");
+       if (!m->jcode && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
+               *exceptionptr = new_classformaterror(c, "Missing Code attribute");
+
+               return false;
+       }
+
+       /* everything was ok */
+
+       return true;
 }
 
 
 }
 
 
@@ -1276,9 +1488,9 @@ void method_display_flags_last(methodinfo *m)
        Check if m and old are identical with respect to type and name. This means
        that old can be overwritten with m.
        
        Check if m and old are identical with respect to type and name. This means
        that old can be overwritten with m.
        
-*******************************************************************************/  
+*******************************************************************************/
 
 
-static bool method_canoverwrite (methodinfo *m, methodinfo *old)
+static bool method_canoverwrite(methodinfo *m, methodinfo *old)
 {
        if (m->name != old->name) return false;
        if (m->descriptor != old->descriptor) return false;
 {
        if (m->name != old->name) return false;
        if (m->descriptor != old->descriptor) return false;
@@ -1287,14 +1499,12 @@ static bool method_canoverwrite (methodinfo *m, methodinfo *old)
 }
 
 
 }
 
 
-
-
 /******************************************************************************/
 /************************ Functions for class *********************************/
 /******************************************************************************/
 
 
 /******************************************************************************/
 /************************ Functions for class *********************************/
 /******************************************************************************/
 
 
-/******************** function:: class_getconstant ******************************
+/******************** 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
 
        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
@@ -1344,7 +1554,7 @@ u4 class_constanttype(classinfo *c, u4 pos)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-static void class_loadcpool(classinfo *c)
+static bool class_loadcpool(classbuffer *cb, classinfo *c)
 {
 
        /* The following structures are used to save information which cannot be 
 {
 
        /* The following structures are used to save information which cannot be 
@@ -1392,235 +1602,303 @@ static void class_loadcpool(classinfo *c)
        forward_nameandtype *forward_nameandtypes = NULL;
        forward_fieldmethint *forward_fieldmethints = NULL;
 
        forward_nameandtype *forward_nameandtypes = NULL;
        forward_fieldmethint *forward_fieldmethints = NULL;
 
+       u4 cpcount;
+       u1 *cptags;
+       voidptr *cpinfos;
+
        /* number of entries in the constant_pool table plus one */
        /* number of entries in the constant_pool table plus one */
-       u4 cpcount       = c -> cpcount = suck_u2();
+       if (!check_classbuffer_size(cb, 2))
+               return false;
+
+       cpcount = c->cpcount = suck_u2(cb);
+
        /* allocate memory */
        /* allocate memory */
-       u1 *cptags       = c -> cptags  = MNEW (u1, cpcount);
-       voidptr *cpinfos = c -> cpinfos = MNEW (voidptr, cpcount);
+       cptags  = c->cptags  = MNEW(u1, cpcount);
+       cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
 
        if (!cpcount)
                panic("Invalid constant_pool_count (0)");
        
 
        if (!cpcount)
                panic("Invalid constant_pool_count (0)");
        
-#ifdef STATISTICS
-       count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_const_pool_len += (sizeof(voidptr) + 1) * cpcount;
 #endif
        
        /* initialize constantpool */
 #endif
        
        /* initialize constantpool */
-       for (idx=0; idx<cpcount; idx++) {
+       for (idx = 0; idx < cpcount; idx++) {
                cptags[idx] = CONSTANT_UNUSED;
                cpinfos[idx] = NULL;
                cptags[idx] = CONSTANT_UNUSED;
                cpinfos[idx] = NULL;
-               }
+       }
 
                        
 
                        
-               /******* first pass *******/
-               /* entries which cannot be resolved now are written into 
-                  temporary structures and traversed again later        */
+       /******* first pass *******/
+       /* entries which cannot be resolved now are written into 
+          temporary structures and traversed again later        */
                   
        idx = 1;
        while (idx < cpcount) {
                   
        idx = 1;
        while (idx < cpcount) {
+               u4 t;
+
                /* get constant type */
                /* get constant type */
-               u4 t = suck_u1 (); 
-               switch ( t ) {
+               if (!check_classbuffer_size(cb, 1))
+                       return false;
 
 
-                       case CONSTANT_Class: { 
-                               forward_class *nfc = DNEW(forward_class);
+               t = suck_u1(cb);
 
 
-                               nfc -> next = forward_classes;                                                                                  
-                               forward_classes = nfc;
+               switch (t) {
+               case CONSTANT_Class: { 
+                       forward_class *nfc = DNEW(forward_class);
 
 
-                               nfc -> thisindex = idx;
-                               /* reference to CONSTANT_NameAndType */
-                               nfc -> name_index = suck_u2 (); 
+                       nfc->next = forward_classes;
+                       forward_classes = nfc;
 
 
-                               idx++;
-                               break;
-                               }
+                       nfc->thisindex = idx;
+                       /* reference to CONSTANT_NameAndType */
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       nfc->name_index = suck_u2(cb);
+
+                       idx++;
+                       break;
+               }
                        
                        
-                       case CONSTANT_Fieldref:
-                       case CONSTANT_Methodref:
-                       case CONSTANT_InterfaceMethodref: { 
-                               forward_fieldmethint *nff = DNEW (forward_fieldmethint);
+               case CONSTANT_Fieldref:
+               case CONSTANT_Methodref:
+               case CONSTANT_InterfaceMethodref: { 
+                       forward_fieldmethint *nff = DNEW(forward_fieldmethint);
                                
                                
-                               nff -> next = forward_fieldmethints;
-                               forward_fieldmethints = nff;
-
-                               nff -> thisindex = idx;
-                               /* constant type */
-                               nff -> tag = t;
-                               /* class or interface type that contains the declaration of the field or method */
-                               nff -> class_index = suck_u2 (); 
-                               /* name and descriptor of the field or method */
-                               nff -> nameandtype_index = suck_u2 ();
-
-                               idx ++;
-                               break;
-                               }
+                       nff->next = forward_fieldmethints;
+                       forward_fieldmethints = nff;
+
+                       nff->thisindex = idx;
+                       /* constant type */
+                       nff->tag = t;
+
+                       if (!check_classbuffer_size(cb, 2 + 2))
+                               return false;
+
+                       /* class or interface type that contains the declaration of the
+                          field or method */
+                       nff->class_index = suck_u2(cb);
+
+                       /* name and descriptor of the field or method */
+                       nff->nameandtype_index = suck_u2(cb);
+
+                       idx++;
+                       break;
+               }
                                
                                
-                       case CONSTANT_String: {
-                               forward_string *nfs = DNEW (forward_string);
+               case CONSTANT_String: {
+                       forward_string *nfs = DNEW(forward_string);
                                
                                
-                               nfs -> next = forward_strings;
-                               forward_strings = nfs;
+                       nfs->next = forward_strings;
+                       forward_strings = nfs;
                                
                                
-                               nfs -> thisindex = idx;
-                               /* reference to CONSTANT_Utf8_info with string characters */
-                               nfs -> string_index = suck_u2 ();
+                       nfs->thisindex = idx;
+
+                       /* reference to CONSTANT_Utf8_info with string characters */
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       nfs->string_index = suck_u2(cb);
                                
                                
-                               idx ++;
-                               break;
-                               }
+                       idx++;
+                       break;
+               }
 
 
-                       case CONSTANT_NameAndType: {
-                               forward_nameandtype *nfn = DNEW (forward_nameandtype);
+               case CONSTANT_NameAndType: {
+                       forward_nameandtype *nfn = DNEW(forward_nameandtype);
                                
                                
-                               nfn -> next = forward_nameandtypes;
-                               forward_nameandtypes = nfn;
+                       nfn->next = forward_nameandtypes;
+                       forward_nameandtypes = nfn;
                                
                                
-                               nfn -> thisindex = idx;
-                               /* reference to CONSTANT_Utf8_info containing simple name */
-                               nfn -> name_index = suck_u2 ();
-                               /* reference to CONSTANT_Utf8_info containing field or method descriptor */
-                               nfn -> sig_index = suck_u2 ();
+                       nfn->thisindex = idx;
+
+                       if (!check_classbuffer_size(cb, 2 + 2))
+                               return false;
+
+                       /* reference to CONSTANT_Utf8_info containing simple name */
+                       nfn->name_index = suck_u2(cb);
+
+                       /* reference to CONSTANT_Utf8_info containing field or method
+                          descriptor */
+                       nfn->sig_index = suck_u2(cb);
                                
                                
-                               idx ++;
-                               break;
-                               }
+                       idx++;
+                       break;
+               }
 
 
-                       case CONSTANT_Integer: {
-                               constant_integer *ci = NEW (constant_integer);
+               case CONSTANT_Integer: {
+                       constant_integer *ci = NEW(constant_integer);
 
 
-#ifdef STATISTICS
-       count_const_pool_len += sizeof(constant_integer);
+#if defined(STATISTICS)
+                       if (opt_stat)
+                               count_const_pool_len += sizeof(constant_integer);
 #endif
 
 #endif
 
-                               ci -> value = suck_s4 ();
-                               cptags [idx] = CONSTANT_Integer;
-                               cpinfos [idx] = ci;
-                               idx ++;
-                               
-                               break;
-                               }
+                       if (!check_classbuffer_size(cb, 4))
+                               return false;
+
+                       ci->value = suck_s4(cb);
+                       cptags[idx] = CONSTANT_Integer;
+                       cpinfos[idx] = ci;
+
+                       idx++;
+                       break;
+               }
                                
                                
-                       case CONSTANT_Float: {
-                               constant_float *cf = NEW (constant_float);
+               case CONSTANT_Float: {
+                       constant_float *cf = NEW(constant_float);
 
 
-#ifdef STATISTICS
-       count_const_pool_len += sizeof(constant_float);
+#if defined(STATISTICS)
+                       if (opt_stat)
+                               count_const_pool_len += sizeof(constant_float);
 #endif
 
 #endif
 
-                               cf -> value = suck_float ();
-                               cptags [idx] = CONSTANT_Float;
-                               cpinfos[idx] = cf;
-                               idx ++;
-                               break;
-                               }
+                       if (!check_classbuffer_size(cb, 4))
+                               return false;
+
+                       cf->value = suck_float(cb);
+                       cptags[idx] = CONSTANT_Float;
+                       cpinfos[idx] = cf;
+
+                       idx++;
+                       break;
+               }
                                
                                
-                       case CONSTANT_Long: {
-                               constant_long *cl = NEW(constant_long);
+               case CONSTANT_Long: {
+                       constant_long *cl = NEW(constant_long);
                                        
                                        
-#ifdef STATISTICS
-       count_const_pool_len += sizeof(constant_long);
+#if defined(STATISTICS)
+                       if (opt_stat)
+                               count_const_pool_len += sizeof(constant_long);
 #endif
 
 #endif
 
-                               cl -> value = suck_s8 ();
-                               cptags [idx] = CONSTANT_Long;
-                               cpinfos [idx] = cl;
-                               idx += 2;
-                               if (idx > cpcount)
-                                       panic("Long constant exceeds constant pool");
-                               break;
-                               }
+                       if (!check_classbuffer_size(cb, 8))
+                               return false;
+
+                       cl->value = suck_s8(cb);
+                       cptags[idx] = CONSTANT_Long;
+                       cpinfos[idx] = cl;
+                       idx += 2;
+                       if (idx > cpcount)
+                               panic("Long constant exceeds constant pool");
+                       break;
+               }
                        
                        
-                       case CONSTANT_Double: {
-                               constant_double *cd = NEW(constant_double);
+               case CONSTANT_Double: {
+                       constant_double *cd = NEW(constant_double);
                                
                                
-#ifdef STATISTICS
-       count_const_pool_len += sizeof(constant_double);
+#if defined(STATISTICS)
+                       if (opt_stat)
+                               count_const_pool_len += sizeof(constant_double);
 #endif
 
 #endif
 
-                               cd -> value = suck_double ();
-                               cptags [idx] = CONSTANT_Double;
-                               cpinfos [idx] = cd;
-                               idx += 2;
-                               if (idx > cpcount)
-                                       panic("Double constant exceeds constant pool");
-                               break;
-                               }
+                       if (!check_classbuffer_size(cb, 8))
+                               return false;
+
+                       cd->value = suck_double(cb);
+                       cptags[idx] = CONSTANT_Double;
+                       cpinfos[idx] = cd;
+                       idx += 2;
+                       if (idx > cpcount)
+                               panic("Double constant exceeds constant pool");
+                       break;
+               }
                                
                                
-                       case CONSTANT_Utf8: { 
-
-                               /* number of bytes in the bytes array (not string-length) */
-                               u4 length = suck_u2();
-                               cptags [idx]  = CONSTANT_Utf8;
-                               /* validate the string */
-                               ASSERT_LEFT(length);
-                               if (opt_verify &&
-                                       !is_valid_utf(classbuf_pos+1, classbuf_pos+1+length))
-                               {
-                                       dolog("Invalid UTF-8 string (constant pool index %d)",idx);
-                                       panic("Invalid UTF-8 string");
-                               }
-                               /* insert utf-string into the utf-symboltable */
-                               cpinfos [idx] = utf_new(classbuf_pos+1, length);
-                               /* skip bytes of the string */
-                               skip_nbytes(length);
-                               idx++;
-                               break;
-                               }
+               case CONSTANT_Utf8: { 
+                       u4 length;
+
+                       /* number of bytes in the bytes array (not string-length) */
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       length = suck_u2(cb);
+                       cptags[idx] = CONSTANT_Utf8;
+
+                       /* validate the string */
+                       if (!check_classbuffer_size(cb, length))
+                               return false;
+
+                       if (opt_verify &&
+                               !is_valid_utf(cb->pos + 1, cb->pos + 1 + length)) {
+                               dolog("Invalid UTF-8 string (constant pool index %d)",idx);
+                               panic("Invalid UTF-8 string");
+                       }
+                       /* insert utf-string into the utf-symboltable */
+                       cpinfos[idx] = utf_new_intern(cb->pos + 1, length);
+
+                       /* skip bytes of the string (buffer size check above) */
+                       skip_nbytes(cb, length);
+                       idx++;
+                       break;
+               }
                                                                                
                                                                                
-                       default:
-                               error ("Unkown constant type: %d",(int) t);
-               
-                       }  /* end switch */
-                       
-               } /* end while */
-               
+               default:
+                       error("Unkown constant type: %d",(int) t);
+               }  /* end switch */
+       } /* end while */
 
 
 
 
-          /* resolve entries in temporary structures */
+       /* resolve entries in temporary structures */
 
        while (forward_classes) {
                utf *name =
 
        while (forward_classes) {
                utf *name =
-                 class_getconstant (c, forward_classes -> name_index, CONSTANT_Utf8);
+                       class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
 
                if (opt_verify && !is_valid_name_utf(name))
                        panic("Class reference with invalid name");
 
 
                if (opt_verify && !is_valid_name_utf(name))
                        panic("Class reference with invalid name");
 
-               cptags  [forward_classes -> thisindex] = CONSTANT_Class;
+               cptags[forward_classes->thisindex] = CONSTANT_Class;
                /* retrieve class from class-table */
                /* retrieve class from class-table */
-               cpinfos [forward_classes -> thisindex] = class_new (name);
+               if (opt_eager) {
+                       classinfo *tc;
+                       tc = class_new_intern(name);
 
 
-               forward_classes = forward_classes -> next;
-               
+                       if (!class_load(tc))
+                               return false;
+
+                       /* link the class later, so we cannot link the currently loaded
+                          class */
+                       list_addfirst(&unlinkedclasses, tc);
+
+                       cpinfos[forward_classes->thisindex] = tc;
+
+               } else {
+                       cpinfos[forward_classes->thisindex] = class_new(name);
                }
 
                }
 
+               forward_classes = forward_classes->next;
+       }
+
        while (forward_strings) {
        while (forward_strings) {
-               utf *text = 
-                 class_getconstant (c, forward_strings -> string_index, CONSTANT_Utf8);
-/*
-               log_text("forward_string:");
-               printf( "classpoolid: %d\n",forward_strings -> thisindex);
-               utf_display(text);
-               log_text("\n------------------"); */
+               utf *text =
+                       class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+
                /* resolve utf-string */                
                /* resolve utf-string */                
-               cptags   [forward_strings -> thisindex] = CONSTANT_String;
-               cpinfos  [forward_strings -> thisindex] = text;
+               cptags[forward_strings->thisindex] = CONSTANT_String;
+               cpinfos[forward_strings->thisindex] = text;
                
                
-               forward_strings = forward_strings -> next;
-               }       
+               forward_strings = forward_strings->next;
+       }
 
        while (forward_nameandtypes) {
 
        while (forward_nameandtypes) {
-               constant_nameandtype *cn = NEW (constant_nameandtype);  
+               constant_nameandtype *cn = NEW(constant_nameandtype);   
 
 
-#ifdef STATISTICS
-               count_const_pool_len += sizeof(constant_nameandtype);
+#if defined(STATISTICS)
+               if (opt_stat)
+                       count_const_pool_len += sizeof(constant_nameandtype);
 #endif
 
                /* resolve simple name and descriptor */
 #endif
 
                /* resolve simple name and descriptor */
-               cn -> name = class_getconstant 
-                  (c, forward_nameandtypes -> name_index, CONSTANT_Utf8);
-               cn -> descriptor = class_getconstant
-                  (c, forward_nameandtypes -> sig_index, CONSTANT_Utf8);
+               cn->name = class_getconstant(c,
+                                                                        forward_nameandtypes->name_index,
+                                                                        CONSTANT_Utf8);
+
+               cn->descriptor = class_getconstant(c,
+                                                                                  forward_nameandtypes->sig_index,
+                                                                                  CONSTANT_Utf8);
 
                if (opt_verify) {
                        /* check name */
 
                if (opt_verify) {
                        /* check name */
@@ -1631,64 +1909,53 @@ static void class_loadcpool(classinfo *c)
                                panic("NameAndType with invalid special name");
                }
 
                                panic("NameAndType with invalid special name");
                }
 
-               cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
-               cpinfos  [forward_nameandtypes -> thisindex] = cn;
+               cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
+               cpinfos[forward_nameandtypes->thisindex] = cn;
                
                
-               forward_nameandtypes = forward_nameandtypes -> next;
-               }
-
+               forward_nameandtypes = forward_nameandtypes->next;
+       }
 
 
-       while (forward_fieldmethints)  {
+       while (forward_fieldmethints) {
                constant_nameandtype *nat;
                constant_nameandtype *nat;
-               constant_FMIref *fmi = NEW (constant_FMIref);
+               constant_FMIref *fmi = NEW(constant_FMIref);
 
 
-#ifdef STATISTICS
-               count_const_pool_len += sizeof(constant_FMIref);
+#if defined(STATISTICS)
+               if (opt_stat)
+                       count_const_pool_len += sizeof(constant_FMIref);
 #endif
                /* resolve simple name and descriptor */
 #endif
                /* resolve simple name and descriptor */
-               nat = class_getconstant
-                       (c, forward_fieldmethints -> nameandtype_index, CONSTANT_NameAndType);
-
-#ifdef JOWENN_DEBUG
-               log_text("trying to resolve:");
-               log_text(nat->name->text);
-               switch(forward_fieldmethints ->tag) {
-               case CONSTANT_Fieldref: 
-                               log_text("CONSTANT_Fieldref");
-                               break;
-               case CONSTANT_InterfaceMethodref: 
-                               log_text("CONSTANT_InterfaceMethodref");
-                               break;
-               case CONSTANT_Methodref: 
-                               log_text("CONSTANT_Methodref");
-                               break;
-               }
-#endif
-               fmi -> class = class_getconstant 
-                       (c, forward_fieldmethints -> class_index, CONSTANT_Class);
-               fmi -> name = nat -> name;
-               fmi -> descriptor = nat -> descriptor;
-
-               cptags [forward_fieldmethints -> thisindex] = forward_fieldmethints -> tag;
-               cpinfos [forward_fieldmethints -> thisindex] = fmi;
+               nat = class_getconstant(c,
+                                                               forward_fieldmethints->nameandtype_index,
+                                                               CONSTANT_NameAndType);
+
+               fmi->class = class_getconstant(c,
+                                                                          forward_fieldmethints->class_index,
+                                                                          CONSTANT_Class);
+               fmi->name = nat->name;
+               fmi->descriptor = nat->descriptor;
+
+               cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
+               cpinfos[forward_fieldmethints->thisindex] = fmi;
        
        
-               switch (forward_fieldmethints -> tag) {
+               switch (forward_fieldmethints->tag) {
                case CONSTANT_Fieldref:  /* check validity of descriptor */
                case CONSTANT_Fieldref:  /* check validity of descriptor */
-                                        checkfielddescriptor (fmi->descriptor->text,utf_end(fmi->descriptor));
-                                        break;
-               case CONSTANT_InterfaceMethodref: 
+                       checkfielddescriptor(fmi->descriptor->text,
+                                                                utf_end(fmi->descriptor));
+                       break;
+               case CONSTANT_InterfaceMethodref:
                case CONSTANT_Methodref: /* check validity of descriptor */
                case CONSTANT_Methodref: /* check validity of descriptor */
-                                        checkmethoddescriptor (fmi->descriptor);
-                                        break;
-               }               
+                       checkmethoddescriptor(c, fmi->descriptor);
+                       break;
+               }
        
        
-               forward_fieldmethints = forward_fieldmethints -> next;
+               forward_fieldmethints = forward_fieldmethints->next;
+       }
 
 
-               }
+       dump_release(dumpsize);
 
 
-/*     class_showconstantpool(c); */
+       /* everything was ok */
 
 
-       dump_release (dumpsize);
+       return true;
 }
 
 
 }
 
 
@@ -1705,40 +1972,128 @@ static void class_loadcpool(classinfo *c)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static int class_load(classinfo *c)
+classinfo *class_load_intern(classbuffer *cb);
+
+classinfo *class_load(classinfo *c)
+{
+       classbuffer *cb;
+       classinfo *r;
+       s8 starttime;
+       s8 stoptime;
+
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
+
+       /* maybe the class is already loaded */
+       if (c->loaded) {
+               builtin_monitorexit((java_objectheader *) c);
+
+               return c;
+       }
+
+       /* measure time */
+       if (getloadingtime)
+               starttime = getcputime();
+
+       /* 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)
+                       throw_cacao_exception_exit(string_java_lang_NoClassDefFoundError,
+                                                                          "java/lang/Object");
+
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
+                                                                        c->name);
+
+               builtin_monitorexit((java_objectheader *) c);
+
+               return NULL;
+       }
+       
+       /* call the internal function */
+       r = class_load_intern(cb);
+
+       /* if return value is NULL, we had a problem and the class is not loaded */
+       if (!r) {
+               c->loaded = false;
+
+               /* now free the allocated memory, otherwise we could ran into a DOS */
+               class_remove(c);
+       }
+
+       /* free memory */
+       suck_stop(cb);
+
+       /* measure time */
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime - starttime);
+       }
+
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+
+       return r;
+}
+
+
+classinfo *class_load_intern(classbuffer *cb)
 {
 {
+       classinfo *c;
        u4 i;
        u4 i;
-       u4 mi,ma;
+       u4 mi, ma;
+/*     s4 classdata_left; */
+       char msg[MAXLOGTEXT];               /* maybe we get an exception */
 
 
-#ifdef STATISTICS
-       count_class_loads++;
+       /* get the classbuffer's class */
+       c = cb->class;
+
+       /* maybe the class is already loaded */
+       if (c->loaded)
+               return c;
+
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_class_loads++;
 #endif
 
        /* output for debugging purposes */
 #endif
 
        /* output for debugging purposes */
-       if (loadverbose) {              
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Loading class: ");
-               utf_sprint(logtext + strlen(logtext), c->name);
-               log_text(logtext);
-       }
+       if (loadverbose)
+               log_message_class("Loading class: ", c);
        
        
-       /* load classdata, throw exception on error */
+       /* class is somewhat loaded */
+       c->loaded = true;
 
 
-       if (!suck_start(c->name)) {
-               throw_noclassdeffounderror_message(c->name);
-               return false;
+       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+               return NULL;
+
+       /* check signature */
+       if (suck_u4(cb) != MAGIC) {
+               *exceptionptr = new_classformaterror(c, "Bad magic number");
+
+               return NULL;
        }
        }
-       
-       /* check signature */           
-       if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
+
        /* check version */
        /* check version */
-       mi = suck_u2(); 
-       ma = suck_u2();
-       if (ma != MAJOR_VERSION && (ma != MAJOR_VERSION+1 || mi != 0)) {
-               error("File version %d.%d is not supported", (int) ma, (int) mi);
+       mi = suck_u2(cb);
+       ma = suck_u2(cb);
+
+       if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
+               *exceptionptr =
+                       new_classformaterror(c,
+                                                                "Unsupported major.minor version %d.%d",
+                                                                ma, mi);
+
+               return NULL;
        }
 
        }
 
-       class_loadcpool(c);
+       if (!class_loadcpool(cb, c))
+               return NULL;
+
        /*JOWENN*/
        c->erroneous_state = 0;
        c->initializing_thread = 0;     
        /*JOWENN*/
        c->erroneous_state = 0;
        c->initializing_thread = 0;     
@@ -1747,76 +2102,131 @@ static int class_load(classinfo *c)
        c->impldBy = NULL;
 
        /* ACC flags */
        c->impldBy = NULL;
 
        /* ACC flags */
-       c->flags = suck_u2(); 
+       if (!check_classbuffer_size(cb, 2))
+               return NULL;
+
+       c->flags = suck_u2(cb);
        /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
 
        /* check ACC flags consistency */
        /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
 
        /* check ACC flags consistency */
-       if ((c->flags & ACC_INTERFACE) != 0) {
-               if ((c->flags & ACC_ABSTRACT) == 0) {
+       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"); */
                }
                        /* 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)) != 0)
-                       panic("Interface class has invalid flags");
-               if ((c->flags & (ACC_SUPER)) != 0)
+
+               if (c->flags & ACC_FINAL) {
+                       *exceptionptr =
+                               new_classformaterror(c,
+                                                                        "Illegal class modifiers: 0x%x", c->flags);
+
+                       return NULL;
+               }
+
+               if (c->flags & ACC_SUPER) {
                        c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
                        c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
+               }
+       }
+
+       if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
+               *exceptionptr =
+                       new_classformaterror(c, "Illegal class modifiers: 0x%x", c->flags);
+
+               return NULL;
        }
        }
-       if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL))
-               panic("Class is declared both abstract and final");
+
+       if (!check_classbuffer_size(cb, 2 + 2))
+               return NULL;
 
        /* this class */
 
        /* this class */
-       i = suck_u2();
-       if (class_getconstant(c, i, CONSTANT_Class) != c)
-               panic("Invalid this_class in class file");
+       i = suck_u2(cb);
+       if (class_getconstant(c, i, CONSTANT_Class) != c) {
+               utf_sprint(msg, c->name);
+               sprintf(msg + strlen(msg), " (wrong name: ");
+               utf_sprint(msg + strlen(msg),
+                                  ((classinfo *) class_getconstant(c, i, CONSTANT_Class))->name);
+               sprintf(msg + strlen(msg), ")");
+
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoClassDefFoundError, msg);
+
+               return NULL;
+       }
        
        /* retrieve superclass */
        
        /* retrieve superclass */
-       if ((i = suck_u2())) {
+       if ((i = suck_u2(cb))) {
                c->super = class_getconstant(c, i, CONSTANT_Class);
 
                /* java.lang.Object may not have a super class. */
                c->super = class_getconstant(c, i, CONSTANT_Class);
 
                /* java.lang.Object may not have a super class. */
-               if (c->name == utf_java_lang_Object)
-                       panic("java.lang.Object with super class");
+               if (c->name == utf_java_lang_Object) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_ClassFormatError,
+                                                                         "java.lang.Object with superclass");
 
 
-               /* Interfaces must have j.l.O as super class. */
-               if ((c->flags & ACC_INTERFACE) != 0
-                       && c->super->name != utf_java_lang_Object)
-               {
-                       panic("Interface with super class other than java.lang.Object");
+                       return NULL;
                }
                }
+
+               /* Interfaces must have java.lang.Object as super class. */
+               if ((c->flags & ACC_INTERFACE) &&
+                       c->super->name != utf_java_lang_Object) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_ClassFormatError,
+                                                                         "Interfaces must have java.lang.Object as superclass");
+
+                       return NULL;
+               }
+
        } else {
                c->super = NULL;
 
                /* This is only allowed for java.lang.Object. */
        } else {
                c->super = NULL;
 
                /* This is only allowed for java.lang.Object. */
-               if (c->name != utf_java_lang_Object)
-                       panic("Class (not java.lang.Object) without super class");
+               if (c->name != utf_java_lang_Object) {
+                       *exceptionptr = new_classformaterror(c, "Bad superclass index");
+
+                       return NULL;
+               }
+                       
        }
                         
        /* retrieve interfaces */
        }
                         
        /* retrieve interfaces */
-       c->interfacescount = suck_u2();
+       if (!check_classbuffer_size(cb, 2))
+               return NULL;
+
+       c->interfacescount = suck_u2(cb);
+
+       if (!check_classbuffer_size(cb, 2 * c->interfacescount))
+               return NULL;
+
        c->interfaces = MNEW(classinfo*, c->interfacescount);
        for (i = 0; i < c->interfacescount; i++) {
        c->interfaces = MNEW(classinfo*, c->interfacescount);
        for (i = 0; i < c->interfacescount; i++) {
-               c->interfaces [i] = 
-                       class_getconstant(c, suck_u2(), CONSTANT_Class);
+               c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class);
        }
 
        /* load fields */
        }
 
        /* load fields */
-       c->fieldscount = suck_u2();
-/*     utf_display(c->name);
-       printf(" ,Fieldscount: %d\n",c->fieldscount);*/
+       if (!check_classbuffer_size(cb, 2))
+               return NULL;
 
 
+       c->fieldscount = suck_u2(cb);
        c->fields = GCNEW(fieldinfo, c->fieldscount);
        c->fields = GCNEW(fieldinfo, c->fieldscount);
+/*     c->fields = MNEW(fieldinfo, c->fieldscount); */
        for (i = 0; i < c->fieldscount; i++) {
        for (i = 0; i < c->fieldscount; i++) {
-               field_load(&(c->fields[i]), c);
+               if (!field_load(cb, c, &(c->fields[i])))
+                       return NULL;
        }
 
        /* load methods */
        }
 
        /* load methods */
-       c->methodscount = suck_u2();
-       c->methods = MNEW(methodinfo, c->methodscount);
+       if (!check_classbuffer_size(cb, 2))
+               return NULL;
+
+       c->methodscount = suck_u2(cb);
+       c->methods = GCNEW(methodinfo, c->methodscount);
+/*     c->methods = MNEW(methodinfo, c->methodscount); */
        for (i = 0; i < c->methodscount; i++) {
        for (i = 0; i < c->methodscount; i++) {
-               method_load(&(c->methods[i]), c);
+               if (!method_load(cb, c, &(c->methods[i])))
+                       return NULL;
        }
 
        /* Check if all fields and methods can be uniquely
        }
 
        /* Check if all fields and methods can be uniquely
@@ -1850,85 +2260,100 @@ static int class_load(classinfo *c)
                }
 
                /* Check fields */
                }
 
                /* Check fields */
-               memset(hashtab,0,sizeof(u2) * (hashlen + len));
-               for (i = 0; i<c->fieldscount; ++i) {
+               memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
+               for (i = 0; i < c->fieldscount; ++i) {
                        fieldinfo *fi = c->fields + i;
                        fieldinfo *fi = c->fields + i;
+
                        /* It's ok if we lose bits here */
                        /* It's ok if we lose bits here */
-                       index = ((((size_t)fi->name) + ((size_t)fi->descriptor)) >> shift)
-                                 % hashlen;
-                       if ((old = hashtab[index]) != 0) {
+                       index = ((((size_t) fi->name) +
+                                         ((size_t) fi->descriptor)) >> shift) % hashlen;
+
+                       if ((old = hashtab[index])) {
                                old--;
                                old--;
-                               /* dolog("HASHHIT %d --> %d",index,old); */
                                next[i] = old;
                                do {
                                next[i] = old;
                                do {
-                                       /* dolog("HASHCHECK %d",old); */
-                                       if (c->fields[old].name == fi->name
-                                               && c->fields[old].descriptor == fi->descriptor)
-                                       {
-                                               dolog("Duplicate field (%d,%d):",i,old);
-                                               log_utf(fi->name); log_utf(fi->descriptor);
-                                               panic("Fields with same name and descriptor");
+                                       if (c->fields[old].name == fi->name &&
+                                               c->fields[old].descriptor == fi->descriptor) {
+                                               *exceptionptr =
+                                                       new_classformaterror(c,
+                                                                                                "Repetitive field name/signature");
+
+                                               return NULL;
                                        }
                                        }
-                               } while ((old = next[old]) != 0);
+                               } while ((old = next[old]));
                        }
                        }
-                       /* else dolog("HASHLUCKY"); */
-                       hashtab[index] = i+1;
+                       hashtab[index] = i + 1;
                }
                
                /* Check methods */
                }
                
                /* Check methods */
-               memset(hashtab,0,sizeof(u2) * (hashlen + len));
-               for (i = 0; i<c->methodscount; ++i) {
+               memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
+               for (i = 0; i < c->methodscount; ++i) {
                        methodinfo *mi = c->methods + i;
                        methodinfo *mi = c->methods + i;
+
                        /* It's ok if we lose bits here */
                        /* It's ok if we lose bits here */
-                       index = ((((size_t)mi->name) + ((size_t)mi->descriptor)) >> shift)
-                                 % hashlen;
-                       if ((old = hashtab[index]) != 0) {
+                       index = ((((size_t) mi->name) +
+                                         ((size_t) mi->descriptor)) >> shift) % hashlen;
+
+                       if ((old = hashtab[index])) {
                                old--;
                                old--;
-                               /* dolog("HASHHIT %d --> %d",index,old); */
                                next[i] = old;
                                do {
                                next[i] = old;
                                do {
-                                       /* dolog("HASHCHECK %d",old); */
-                                       if (c->methods[old].name == mi->name
-                                               && c->methods[old].descriptor == mi->descriptor)
-                                       {
-                                               dolog("Duplicate method (%d,%d):",i,old);
-                                               log_utf(mi->name); log_utf(mi->descriptor);
-                                               panic("Methods with same name and descriptor");
+                                       if (c->methods[old].name == mi->name &&
+                                               c->methods[old].descriptor == mi->descriptor) {
+                                               *exceptionptr =
+                                                       new_classformaterror(c,
+                                                                                                "Repetitive method name/signature");
+
+                                               return NULL;
                                        }
                                        }
-                               } while ((old = next[old]) != 0);
+                               } while ((old = next[old]));
                        }
                        }
-                       /* else dolog("HASHLUCKY"); */
-                       hashtab[index] = i+1;
+                       hashtab[index] = i + 1;
                }
                
                }
                
-               MFREE(hashtab,u2,(hashlen + len));
+               MFREE(hashtab, u2, (hashlen + len));
        }
 
        }
 
-#ifdef STATISTICS
-       count_class_infos += sizeof(classinfo*) * c->interfacescount;
-       count_class_infos += sizeof(fieldinfo) * c->fieldscount;
-       count_class_infos += sizeof(methodinfo) * c->methodscount;
+#if defined(STATISTICS)
+       if (opt_stat) {
+               count_class_infos += sizeof(classinfo*) * c->interfacescount;
+               count_class_infos += sizeof(fieldinfo) * c->fieldscount;
+               count_class_infos += sizeof(methodinfo) * c->methodscount;
+       }
 #endif
 
        /* load variable-length attribute structures */ 
 #endif
 
        /* load variable-length attribute structures */ 
-       attribute_load(suck_u2(), c);
+       if (!check_classbuffer_size(cb, 2))
+               return NULL;
 
 
-       /* free memory */
-       suck_stop();
+       if (!attribute_load(cb, c, suck_u2(cb)))
+               return NULL;
 
 
-       /* remove class from list of unloaded classes and 
-          add to list of unlinked classes                */
-       list_remove(&unloadedclasses, c);
-       list_addlast(&unlinkedclasses, c);
+#if 0
+       /* XXX TWISTI is this still in the JVM spec? SUN and IBM don't complain about it */
+       
+       /* check if all data has been read */
+       classdata_left = ((cb->data + cb->size) - cb->pos - 1);
 
 
-       c->loaded = true;
+       if (classdata_left > 0) {
+               /* surplus */           
+               dolog("There are %d extra bytes at end of classfile", classdata_left);
+               /* The JVM spec disallows extra bytes. */
+               panic("Extra bytes at end of classfile");
+       }
+#endif
 
 
-       return true;
+       if (loadverbose)
+               log_message_class("Loading done class: ", c);
+
+       return c;
 }
 
 
 
 }
 
 
 
-/************** internal Function: class_highestinterface ***********************
+/************** internal Function: class_highestinterface **********************
 
        Used by the function class_link to determine the amount of memory needed
        for the interface table.
 
        Used by the function class_link to determine the amount of memory needed
        for the interface table.
@@ -1962,16 +2387,17 @@ static s4 class_highestinterface(classinfo *c)
        Is needed by class_link for adding a VTBL to a class. All interfaces
        implemented by ic are added as well.
 
        Is needed by class_link for adding a VTBL to a class. All interfaces
        implemented by ic are added as well.
 
-*******************************************************************************/       
+*******************************************************************************/
 
 
-static void class_addinterface (classinfo *c, classinfo *ic)
+static void class_addinterface(classinfo *c, classinfo *ic)
 {
        s4     j, m;
        s4     i     = ic->index;
 {
        s4     j, m;
        s4     i     = ic->index;
-       vftbl *vftbl = c->vftbl;
-       
+       vftbl_t *vftbl = c->vftbl;
+
        if (i >= vftbl->interfacetablelength)
                panic ("Inernal error: interfacetable overflow");
        if (i >= vftbl->interfacetablelength)
                panic ("Inernal error: interfacetable overflow");
+
        if (vftbl->interfacetable[-i])
                return;
 
        if (vftbl->interfacetable[-i])
                return;
 
@@ -1979,32 +2405,34 @@ static void class_addinterface (classinfo *c, classinfo *ic)
                vftbl->interfacevftbllength[i] = 1;
                vftbl->interfacetable[-i] = MNEW(methodptr, 1);
                vftbl->interfacetable[-i][0] = NULL;
                vftbl->interfacevftbllength[i] = 1;
                vftbl->interfacetable[-i] = MNEW(methodptr, 1);
                vftbl->interfacetable[-i][0] = NULL;
-               }
-       else {
+
+       else {
                vftbl->interfacevftbllength[i] = ic->methodscount;
                vftbl->interfacevftbllength[i] = ic->methodscount;
-               vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
+               vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
 
 #ifdef STATISTICS
 
 #ifdef STATISTICS
-       count_vftbl_len += sizeof(methodptr) *
-                                (ic->methodscount + (ic->methodscount == 0));
+               if (opt_stat)
+                       count_vftbl_len += sizeof(methodptr) *
+                               (ic->methodscount + (ic->methodscount == 0));
 #endif
 
 #endif
 
-               for (j=0; j<ic->methodscount; j++) {
+               for (j = 0; j < ic->methodscount; j++) {
                        classinfo *sc = c;
                        while (sc) {
                                for (m = 0; m < sc->methodscount; m++) {
                                        methodinfo *mi = &(sc->methods[m]);
                                        if (method_canoverwrite(mi, &(ic->methods[j]))) {
                        classinfo *sc = c;
                        while (sc) {
                                for (m = 0; m < sc->methodscount; m++) {
                                        methodinfo *mi = &(sc->methods[m]);
                                        if (method_canoverwrite(mi, &(ic->methods[j]))) {
-                                               vftbl->interfacetable[-i][j] = 
-                                                                         vftbl->table[mi->vftblindex];
+                                               vftbl->interfacetable[-i][j] =
+                                                       vftbl->table[mi->vftblindex];
                                                goto foundmethod;
                                                goto foundmethod;
-                                               }
                                        }
                                        }
-                               sc = sc->super;
                                }
                                }
-                        foundmethod: ;
+                               sc = sc->super;
                        }
                        }
+               foundmethod:
+                       ;
                }
                }
+       }
 
        for (j = 0; j < ic->interfacescount; j++) 
                class_addinterface(c, ic->interfaces[j]);
 
        for (j = 0; j < ic->interfacescount; j++) 
                class_addinterface(c, ic->interfaces[j]);
@@ -2023,11 +2451,6 @@ void class_new_array(classinfo *c)
        methodinfo *clone;
        int namelen;
 
        methodinfo *clone;
        int namelen;
 
-       /* DEBUG */ /* dolog("class_new_array: %s",c->name->text); */
-
-       /* Array classes are not loaded from classfiles. */
-       list_remove(&unloadedclasses, c);
-
        /* Check array class name */
        namelen = c->name->blength;
        if (namelen < 2 || c->name->text[0] != '[')
        /* Check array class name */
        namelen = c->name->blength;
        if (namelen < 2 || c->name->text[0] != '[')
@@ -2035,17 +2458,34 @@ void class_new_array(classinfo *c)
 
        /* Check the component type */
        switch (c->name->text[1]) {
 
        /* Check the component type */
        switch (c->name->text[1]) {
-         case '[':
-                 /* c is an array of arrays. We have to create the component class. */
-                 comp = class_new(utf_new(c->name->text + 1,namelen - 1));
-                 break;
+       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);
 
 
-         case 'L':
-                 /* c is an array of objects. */
-                 if (namelen < 4 || c->name->text[namelen - 1] != ';')
-                         panic("Invalid array class name");
-                 comp = class_new(utf_new(c->name->text + 2,namelen - 3));
-                 break;
+               } else {
+                       comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
+               }
+               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);
+
+               } else {
+                       comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
+               }
+               break;
        }
 
        /* Setup the array class */
        }
 
        /* Setup the array class */
@@ -2053,12 +2493,28 @@ void class_new_array(classinfo *c)
        c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
 
     c->interfacescount = 2;
        c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
 
     c->interfacescount = 2;
-    c->interfaces = MNEW(classinfo*,2);
-    c->interfaces[0] = class_java_lang_Cloneable;
-    c->interfaces[1] = class_java_io_Serializable;
+    c->interfaces = MNEW(classinfo*, 2);
+
+       if (opt_eager) {
+               classinfo *tc;
+
+               tc = class_new_intern(utf_new_char("java/lang/Cloneable"));
+               class_load(tc);
+               list_addfirst(&unlinkedclasses, tc);
+               c->interfaces[0] = tc;
+
+               tc = class_new_intern(utf_new_char("java/io/Serializable"));
+               class_load(tc);
+               list_addfirst(&unlinkedclasses, tc);
+               c->interfaces[1] = 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->methodscount = 1;
 
        c->methodscount = 1;
-       c->methods = MNEW (methodinfo, c->methodscount);
+       c->methods = MNEW(methodinfo, c->methodscount);
 
        clone = c->methods;
        memset(clone, 0, sizeof(methodinfo));
 
        clone = c->methods;
        memset(clone, 0, sizeof(methodinfo));
@@ -2071,17 +2527,8 @@ void class_new_array(classinfo *c)
 
        /* XXX: field: length? */
 
 
        /* XXX: field: length? */
 
-       /* The array class has to be linked */
-       list_addlast(&unlinkedclasses,c);
-       
-       /*
-     * Array classes which are created after the other classes have been
-     * loaded and linked are linked explicitely.
-     */
-        c->loaded=true;
-     
-       if (loader_inited)
-               loader_load(c->name); /* XXX handle errors */
+       /* array classes are not loaded from class files */
+       c->loaded = true;
 }
 
 
 }
 
 
@@ -2098,28 +2545,35 @@ void class_new_array(classinfo *c)
 static arraydescriptor *class_link_array(classinfo *c)
 {
        classinfo *comp = NULL;
 static arraydescriptor *class_link_array(classinfo *c)
 {
        classinfo *comp = NULL;
-       int namelen = c->name->blength;
+       s4 namelen = c->name->blength;
        arraydescriptor *desc;
        arraydescriptor *desc;
-       vftbl *compvftbl;
+       vftbl_t *compvftbl;
 
        /* Check the component type */
        switch (c->name->text[1]) {
 
        /* Check the component type */
        switch (c->name->text[1]) {
-         case '[':
-                 /* c is an array of arrays. */
-                 comp = class_get(utf_new(c->name->text + 1,namelen - 1));
-                 if (!comp) panic("Could not find component array class.");
-                 break;
-
-         case 'L':
-                 /* c is an array of objects. */
-                 comp = class_get(utf_new(c->name->text + 2,namelen - 3));
-                 if (!comp) panic("Could not find component class.");
-                 break;
+       case '[':
+               /* c is an array of arrays. */
+/*             comp = class_get(utf_new_intern(c->name->text + 1, namelen - 1)); */
+               comp = class_new(utf_new_intern(c->name->text + 1, namelen - 1));
+               if (!comp)
+                       panic("Could not find component array class.");
+               break;
+
+       case 'L':
+               /* c is an array of objects. */
+/*             comp = class_get(utf_new_intern(c->name->text + 2, namelen - 3)); */
+               comp = class_new(utf_new_intern(c->name->text + 2, namelen - 3));
+               if (!comp)
+                       panic("Could not find component class.");
+               break;
        }
 
        }
 
-       /* If the component type has not been linked return NULL */
-       if (comp && !comp->linked)
-               return NULL;
+       /* If the component type has not been linked, link it now */
+       if (comp && !comp->linked) {
+               if (!comp->loaded)
+                       class_load(comp);
+               class_link(comp);
+       }
 
        /* Allocate the arraydescriptor */
        desc = NEW(arraydescriptor);
 
        /* Allocate the arraydescriptor */
        desc = NEW(arraydescriptor);
@@ -2128,7 +2582,7 @@ static arraydescriptor *class_link_array(classinfo *c)
                /* c is an array of references */
                desc->arraytype = ARRAYTYPE_OBJECT;
                desc->componentsize = sizeof(void*);
                /* c is an array of references */
                desc->arraytype = ARRAYTYPE_OBJECT;
                desc->componentsize = sizeof(void*);
-               desc->dataoffset = OFFSET(java_objectarray,data);
+               desc->dataoffset = OFFSET(java_objectarray, data);
                
                compvftbl = comp->vftbl;
                if (!compvftbl)
                
                compvftbl = comp->vftbl;
                if (!compvftbl)
@@ -2141,8 +2595,8 @@ static arraydescriptor *class_link_array(classinfo *c)
                                panic("Creating array of dimension >255");
                        desc->dimension = compvftbl->arraydesc->dimension + 1;
                        desc->elementtype = compvftbl->arraydesc->elementtype;
                                panic("Creating array of dimension >255");
                        desc->dimension = compvftbl->arraydesc->dimension + 1;
                        desc->elementtype = compvftbl->arraydesc->elementtype;
-               }
-               else {
+
+               else {
                        desc->elementvftbl = compvftbl;
                        desc->dimension = 1;
                        desc->elementtype = ARRAYTYPE_OBJECT;
                        desc->elementvftbl = compvftbl;
                        desc->dimension = 1;
                        desc->elementtype = ARRAYTYPE_OBJECT;
@@ -2151,42 +2605,50 @@ static arraydescriptor *class_link_array(classinfo *c)
        } else {
                /* c is an array of a primitive type */
                switch (c->name->text[1]) {
        } else {
                /* c is an array of a primitive type */
                switch (c->name->text[1]) {
-               case 'Z': desc->arraytype = ARRAYTYPE_BOOLEAN;
+               case 'Z':
+                       desc->arraytype = ARRAYTYPE_BOOLEAN;
                        desc->dataoffset = OFFSET(java_booleanarray,data);
                        desc->componentsize = sizeof(u1);
                        break;
 
                        desc->dataoffset = OFFSET(java_booleanarray,data);
                        desc->componentsize = sizeof(u1);
                        break;
 
-               case 'B': desc->arraytype = ARRAYTYPE_BYTE;
+               case 'B':
+                       desc->arraytype = ARRAYTYPE_BYTE;
                        desc->dataoffset = OFFSET(java_bytearray,data);
                        desc->componentsize = sizeof(u1);
                        break;
 
                        desc->dataoffset = OFFSET(java_bytearray,data);
                        desc->componentsize = sizeof(u1);
                        break;
 
-               case 'C': desc->arraytype = ARRAYTYPE_CHAR;
+               case 'C':
+                       desc->arraytype = ARRAYTYPE_CHAR;
                        desc->dataoffset = OFFSET(java_chararray,data);
                        desc->componentsize = sizeof(u2);
                        break;
 
                        desc->dataoffset = OFFSET(java_chararray,data);
                        desc->componentsize = sizeof(u2);
                        break;
 
-               case 'D': desc->arraytype = ARRAYTYPE_DOUBLE;
+               case 'D':
+                       desc->arraytype = ARRAYTYPE_DOUBLE;
                        desc->dataoffset = OFFSET(java_doublearray,data);
                        desc->componentsize = sizeof(double);
                        break;
 
                        desc->dataoffset = OFFSET(java_doublearray,data);
                        desc->componentsize = sizeof(double);
                        break;
 
-               case 'F': desc->arraytype = ARRAYTYPE_FLOAT;
+               case 'F':
+                       desc->arraytype = ARRAYTYPE_FLOAT;
                        desc->dataoffset = OFFSET(java_floatarray,data);
                        desc->componentsize = sizeof(float);
                        break;
 
                        desc->dataoffset = OFFSET(java_floatarray,data);
                        desc->componentsize = sizeof(float);
                        break;
 
-               case 'I': desc->arraytype = ARRAYTYPE_INT;
+               case 'I':
+                       desc->arraytype = ARRAYTYPE_INT;
                        desc->dataoffset = OFFSET(java_intarray,data);
                        desc->componentsize = sizeof(s4);
                        break;
 
                        desc->dataoffset = OFFSET(java_intarray,data);
                        desc->componentsize = sizeof(s4);
                        break;
 
-               case 'J': desc->arraytype = ARRAYTYPE_LONG;
+               case 'J':
+                       desc->arraytype = ARRAYTYPE_LONG;
                        desc->dataoffset = OFFSET(java_longarray,data);
                        desc->componentsize = sizeof(s8);
                        break;
 
                        desc->dataoffset = OFFSET(java_longarray,data);
                        desc->componentsize = sizeof(s8);
                        break;
 
-               case 'S': desc->arraytype = ARRAYTYPE_SHORT;
+               case 'S':
+                       desc->arraytype = ARRAYTYPE_SHORT;
                        desc->dataoffset = OFFSET(java_shortarray,data);
                        desc->componentsize = sizeof(s2);
                        break;
                        desc->dataoffset = OFFSET(java_shortarray,data);
                        desc->componentsize = sizeof(s2);
                        break;
@@ -2207,45 +2669,100 @@ static arraydescriptor *class_link_array(classinfo *c)
 
 /********************** Function: class_link ***********************************
 
 
 /********************** Function: class_link ***********************************
 
-       Tries to link a class. The super class and every implemented interface must
-       already have been linked. The function calculates the length in bytes that
+       Tries to link a class. The function calculates the length in bytes that
        an instance of this class requires as well as the VTBL for methods and
        interface methods.
        
        an instance of this class requires as well as the VTBL for methods and
        interface methods.
        
-       If the class can be linked, it is removed from the list 'unlinkedclasses'
-       and added to 'linkedclasses'. Otherwise, it is moved to the end of
-       'unlinkedclasses'.
+*******************************************************************************/
 
 
-       Attention: If cyclical class definitions are encountered, the program gets
-       into an infinite loop (we'll have to work that out)
+static classinfo *class_link_intern(classinfo *c);
 
 
-*******************************************************************************/
+classinfo *class_link(classinfo *c)
+{
+       classinfo *r;
+       s8 starttime;
+       s8 stoptime;
+
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
+
+       /* maybe the class is already linked */
+       if (c->linked) {
+               builtin_monitorexit((java_objectheader *) c);
+
+               return c;
+       }
 
 
-void class_link(classinfo *c)
+       /* measure time */
+       if (getloadingtime)
+               starttime = getcputime();
+
+       /* call the internal function */
+       r = class_link_intern(c);
+
+       /* if return value is NULL, we had a problem and the class is not linked */
+       if (!r)
+               c->linked = false;
+
+       /* measure time */
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime - starttime);
+       }
+
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+
+       return r;
+}
+
+
+static classinfo *class_link_intern(classinfo *c)
 {
        s4 supervftbllength;          /* vftbllegnth of super class               */
        s4 vftbllength;               /* vftbllength of current class             */
        s4 interfacetablelength;      /* interface table length                   */
        classinfo *super = c->super;  /* super class                              */
        classinfo *ic, *c2;           /* intermediate class variables             */
 {
        s4 supervftbllength;          /* vftbllegnth of super class               */
        s4 vftbllength;               /* vftbllength of current class             */
        s4 interfacetablelength;      /* interface table length                   */
        classinfo *super = c->super;  /* super class                              */
        classinfo *ic, *c2;           /* intermediate class variables             */
-       vftbl *v;                     /* vftbl of current class                   */
+       vftbl_t *v;                   /* vftbl of current class                   */
        s4 i;                         /* interface/method/field counter           */
        arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
 
        s4 i;                         /* interface/method/field counter           */
        arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
 
+       /* maybe the class is already linked */
+       if (c->linked)
+               return c;
 
 
-       /*  check if all superclasses are already linked, if not put c at end of
-           unlinked list and return. Additionally initialize class fields.       */
+       if (linkverbose)
+               log_message_class("Linking class: ", c);
 
 
-       /*  check interfaces */
+       /* ok, this class is somewhat linked */
+       c->linked = true;
+
+       /* check interfaces */
 
        for (i = 0; i < c->interfacescount; i++) {
                ic = c->interfaces[i];
 
        for (i = 0; i < c->interfacescount; i++) {
                ic = c->interfaces[i];
-               if (!ic->linked) {
-                       list_remove(&unlinkedclasses, c);
-                       list_addlast(&unlinkedclasses, c);
-                       return; 
+
+               /* detect circularity */
+               if (ic == c) {
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_ClassCircularityError,
+                                                                                c->name);
+
+                       return NULL;
                }
                }
-               if ((ic->flags & ACC_INTERFACE) == 0) {
+
+               if (!ic->loaded)
+                       if (!class_load(ic))
+                               return NULL;
+
+               if (!ic->linked)
+                       if (!class_link(ic))
+                               return NULL;
+
+               if (!(ic->flags & ACC_INTERFACE)) {
                        dolog("Specified interface is not declared as interface:");
                        log_utf(ic->name);
                        dolog("in");
                        dolog("Specified interface is not declared as interface:");
                        log_utf(ic->name);
                        dolog("in");
@@ -2256,7 +2773,7 @@ void class_link(classinfo *c)
        
        /*  check super class */
 
        
        /*  check super class */
 
-       if (super == NULL) {          /* class java.long.Object */
+       if (super == NULL) {          /* class java.lang.Object */
                c->index = 0;
         c->classUsed = USED;     /* Object class is always used CO-RT*/
                c->impldBy = NULL;
                c->index = 0;
         c->classUsed = USED;     /* Object class is always used CO-RT*/
                c->impldBy = NULL;
@@ -2267,26 +2784,36 @@ void class_link(classinfo *c)
                c->finalizer = NULL;
 
        } else {
                c->finalizer = NULL;
 
        } else {
-               if (!super->linked) {
-                       list_remove(&unlinkedclasses, c);
-                       list_addlast(&unlinkedclasses, c);
-                       return; 
+               /* detect circularity */
+               if (super == c) {
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_ClassCircularityError,
+                                                                                c->name);
+
+                       return NULL;
                }
 
                }
 
-               if ((super->flags & ACC_INTERFACE) != 0)
+               if (!super->loaded)
+                       if (!class_load(super))
+                               return NULL;
+
+               if (!super->linked)
+                       if (!class_link(super))
+                               return NULL;
+
+               if (super->flags & ACC_INTERFACE)
                        panic("Interface specified as super class");
 
                /* handle array classes */
                /* The component class must have been linked already. */
                        panic("Interface specified as super class");
 
                /* handle array classes */
                /* The component class must have been linked already. */
-               if (c->name->text[0] == '[')
+               if (c->name->text[0] == '[') {
                        if ((arraydesc = class_link_array(c)) == NULL) {
                        if ((arraydesc = class_link_array(c)) == NULL) {
-                               list_remove(&unlinkedclasses, c);
-                               list_addlast(&unlinkedclasses, c);
-                               return; 
+                               panic("class_link: class_link_array");
                        }
                        }
+               }
 
                /* Don't allow extending final classes */
 
                /* Don't allow extending final classes */
-               if ((super->flags & ACC_FINAL) != 0)
+               if (super->flags & ACC_FINAL)
                        panic("Trying to extend final class");
                
                if (c->flags & ACC_INTERFACE)
                        panic("Trying to extend final class");
                
                if (c->flags & ACC_INTERFACE)
@@ -2301,14 +2828,6 @@ void class_link(classinfo *c)
                c->finalizer = super->finalizer;
        }
 
                c->finalizer = super->finalizer;
        }
 
-
-       if (linkverbose) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Linking Class: ");
-               utf_sprint(logtext + strlen(logtext), c->name );
-               log_text(logtext);
-       }
-
        /* compute vftbl length */
 
        for (i = 0; i < c->methodscount; i++) {
        /* compute vftbl length */
 
        for (i = 0; i < c->methodscount; i++) {
@@ -2317,11 +2836,12 @@ void class_link(classinfo *c)
                if (!(m->flags & ACC_STATIC)) { /* is instance method */
                        classinfo *sc = super;
                        while (sc) {
                if (!(m->flags & ACC_STATIC)) { /* is instance method */
                        classinfo *sc = super;
                        while (sc) {
-                               int j;
+                               s4 j;
                                for (j = 0; j < sc->methodscount; j++) {
                                        if (method_canoverwrite(m, &(sc->methods[j]))) {
                                                if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
                                                        goto notfoundvftblindex;
                                for (j = 0; j < sc->methodscount; j++) {
                                        if (method_canoverwrite(m, &(sc->methods[j]))) {
                                                if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
                                                        goto notfoundvftblindex;
+
                                                if ((sc->methods[j].flags & ACC_FINAL) != 0) {
                                                        log_utf(c->name);
                                                        log_utf(sc->name);
                                                if ((sc->methods[j].flags & ACC_FINAL) != 0) {
                                                        log_utf(c->name);
                                                        log_utf(sc->name);
@@ -2337,12 +2857,15 @@ void class_link(classinfo *c)
                        }
                notfoundvftblindex:
                        m->vftblindex = (vftbllength++);
                        }
                notfoundvftblindex:
                        m->vftblindex = (vftbllength++);
-               foundvftblindex: ;
+               foundvftblindex:
+                       ;
                }
        }       
        
                }
        }       
        
-#ifdef STATISTICS
-       count_vftbl_len += sizeof(vftbl) + (sizeof(methodptr) * (vftbllength - 1));
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_vftbl_len +=
+                       sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
 #endif
 
        /* compute interfacetable length */
 #endif
 
        /* compute interfacetable length */
@@ -2351,7 +2874,7 @@ void class_link(classinfo *c)
        c2 = c;
        while (c2) {
                for (i = 0; i < c2->interfacescount; i++) {
        c2 = c;
        while (c2) {
                for (i = 0; i < c2->interfacescount; i++) {
-                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+                       s4 h = class_highestinterface(c2->interfaces[i]) + 1;
                        if (h > interfacetablelength)
                                interfacetablelength = h;
                }
                        if (h > interfacetablelength)
                                interfacetablelength = h;
                }
@@ -2360,16 +2883,17 @@ void class_link(classinfo *c)
 
        /* allocate virtual function table */
 
 
        /* allocate virtual function table */
 
-       v = (vftbl*) mem_alloc(sizeof(vftbl) + sizeof(methodptr) *
+       v = (vftbl_t*) mem_alloc(sizeof(vftbl_t) + sizeof(methodptr) *
                                                   (vftbllength - 1) + sizeof(methodptr*) *
                                                   (interfacetablelength - (interfacetablelength > 0)));
                                                   (vftbllength - 1) + sizeof(methodptr*) *
                                                   (interfacetablelength - (interfacetablelength > 0)));
-       v = (vftbl*) (((methodptr*) v) + (interfacetablelength - 1) *
+       v = (vftbl_t*) (((methodptr*) v) + (interfacetablelength - 1) *
                                  (interfacetablelength > 1));
        c->header.vftbl = c->vftbl = v;
                                  (interfacetablelength > 1));
        c->header.vftbl = c->vftbl = v;
+/*     utf_display_classname(c->name);printf(", c->header.vftbl=%p\n", c->header.vftbl); */
        v->class = c;
        v->vftbllength = vftbllength;
        v->interfacetablelength = interfacetablelength;
        v->class = c;
        v->vftbllength = vftbllength;
        v->interfacetablelength = interfacetablelength;
-       v->arraydesc = arraydesc;
+       v->arraydesc = arraydesc;
 
        /* store interface index in vftbl */
        if (c->flags & ACC_INTERFACE)
 
        /* store interface index in vftbl */
        if (c->flags & ACC_INTERFACE)
@@ -2395,7 +2919,7 @@ void class_link(classinfo *c)
                s4 dsize;
                fieldinfo *f = &(c->fields[i]);
                
                s4 dsize;
                fieldinfo *f = &(c->fields[i]);
                
-               if (!(f->flags & ACC_STATIC) ) {
+               if (!(f->flags & ACC_STATIC)) {
                        dsize = desc_typesize(f->descriptor);
                        c->instancesize = ALIGN(c->instancesize, dsize);
                        f->offset = c->instancesize;
                        dsize = desc_typesize(f->descriptor);
                        c->instancesize = ALIGN(c->instancesize, dsize);
                        f->offset = c->instancesize;
@@ -2407,8 +2931,9 @@ void class_link(classinfo *c)
        
        v->interfacevftbllength = MNEW(s4, interfacetablelength);
 
        
        v->interfacevftbllength = MNEW(s4, interfacetablelength);
 
-#ifdef STATISTICS
-       count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
 #endif
 
        for (i = 0; i < interfacetablelength; i++) {
 #endif
 
        for (i = 0; i < interfacetablelength; i++) {
@@ -2445,10 +2970,14 @@ void class_link(classinfo *c)
 
        /* final tasks */
 
 
        /* final tasks */
 
-       c->linked = true;       
+       loader_compute_subclasses(c);
+
+       if (linkverbose)
+               log_message_class("Linking done class: ", c);
+
+       /* just return c to show that we didn't had a problem */
 
 
-       list_remove(&unlinkedclasses, c);
-       list_addlast(&linkedclasses, c);
+       return c;
 }
 
 
 }
 
 
@@ -2458,44 +2987,49 @@ void class_link(classinfo *c)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-static void class_freecpool (classinfo *c)
+static void class_freecpool(classinfo *c)
 {
        u4 idx;
        u4 tag;
        voidptr info;
        
 {
        u4 idx;
        u4 tag;
        voidptr info;
        
-       for (idx=0; idx < c->cpcount; idx++) {
-               tag = c->cptags[idx];
-               info = c->cpinfos[idx];
+       if (c->cptags && c->cpinfos) {
+               for (idx = 0; idx < c->cpcount; idx++) {
+                       tag = c->cptags[idx];
+                       info = c->cpinfos[idx];
                
                
-               if (info != NULL) {
-                       switch (tag) {
-                       case CONSTANT_Fieldref:
-                       case CONSTANT_Methodref:
-                       case CONSTANT_InterfaceMethodref:
-                               FREE (info, constant_FMIref);
-                               break;
-                       case CONSTANT_Integer:
-                               FREE (info, constant_integer);
-                               break;
-                       case CONSTANT_Float:
-                               FREE (info, constant_float);
-                               break;
-                       case CONSTANT_Long:
-                               FREE (info, constant_long);
-                               break;
-                       case CONSTANT_Double:
-                               FREE (info, constant_double);
-                               break;
-                       case CONSTANT_NameAndType:
-                               FREE (info, constant_nameandtype);
-                               break;
-                       }
+                       if (info != NULL) {
+                               switch (tag) {
+                               case CONSTANT_Fieldref:
+                               case CONSTANT_Methodref:
+                               case CONSTANT_InterfaceMethodref:
+                                       FREE(info, constant_FMIref);
+                                       break;
+                               case CONSTANT_Integer:
+                                       FREE(info, constant_integer);
+                                       break;
+                               case CONSTANT_Float:
+                                       FREE(info, constant_float);
+                                       break;
+                               case CONSTANT_Long:
+                                       FREE(info, constant_long);
+                                       break;
+                               case CONSTANT_Double:
+                                       FREE(info, constant_double);
+                                       break;
+                               case CONSTANT_NameAndType:
+                                       FREE(info, constant_nameandtype);
+                                       break;
+                               }
                        }
                }
                        }
                }
+       }
 
 
-       MFREE (c -> cptags,  u1, c -> cpcount);
-       MFREE (c -> cpinfos, voidptr, c -> cpcount);
+       if (c->cptags)
+               MFREE(c->cptags, u1, c->cpcount);
+
+       if (c->cpinfos)
+               MFREE(c->cpinfos, voidptr, c->cpcount);
 }
 
 
 }
 
 
@@ -2505,21 +3039,27 @@ static void class_freecpool (classinfo *c)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-static void class_free(classinfo *c)
+void class_free(classinfo *c)
 {
        s4 i;
 {
        s4 i;
-       vftbl *v;
+       vftbl_t *v;
                
        class_freecpool(c);
 
                
        class_freecpool(c);
 
-       MFREE(c->interfaces, classinfo*, c->interfacescount);
+       if (c->interfaces)
+               MFREE(c->interfaces, classinfo*, c->interfacescount);
 
 
-       for (i = 0; i < c->fieldscount; i++)
-               field_free(&(c->fields[i]));
+       if (c->fields) {
+               for (i = 0; i < c->fieldscount; i++)
+                       field_free(&(c->fields[i]));
+/*     MFREE(c->fields, fieldinfo, c->fieldscount); */
+       }
        
        
-       for (i = 0; i < c->methodscount; i++)
-               method_free(&(c->methods[i]));
-       MFREE(c->methods, methodinfo, c->methodscount);
+       if (c->methods) {
+               for (i = 0; i < c->methodscount; i++)
+                       method_free(&(c->methods[i]));
+/*     MFREE(c->methods, methodinfo, c->methodscount); */
+       }
 
        if ((v = c->vftbl) != NULL) {
                if (v->arraydesc)
 
        if ((v = c->vftbl) != NULL) {
                if (v->arraydesc)
@@ -2530,21 +3070,21 @@ static void class_free(classinfo *c)
                }
                MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
 
                }
                MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
 
-               i = sizeof(vftbl) + sizeof(methodptr) * (v->vftbllength - 1) +
+               i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
                    sizeof(methodptr*) * (v->interfacetablelength -
                                         (v->interfacetablelength > 0));
                    sizeof(methodptr*) * (v->interfacetablelength -
                                         (v->interfacetablelength > 0));
-               v = (vftbl*) (((methodptr*) v) - (v->interfacetablelength - 1) *
+               v = (vftbl_t*) (((methodptr*) v) - (v->interfacetablelength - 1) *
                                             (v->interfacetablelength > 1));
                mem_free(v, i);
        }
 
                                             (v->interfacetablelength > 1));
                mem_free(v, i);
        }
 
-       if (c->innerclasscount)
+       if (c->innerclass)
                MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
 
        /*      if (c->classvftbl)
                mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
        
                MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
 
        /*      if (c->classvftbl)
                mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
        
-       GCFREE(c);
+/*     GCFREE(c); */
 }
 
 
 }
 
 
@@ -2558,7 +3098,7 @@ static void class_free(classinfo *c)
 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
-       
+
        for (i = 0; i < c->fieldscount; i++) { 
                if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
                        return &(c->fields[i]);                                                         
        for (i = 0; i < c->fieldscount; i++) { 
                if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) 
                        return &(c->fields[i]);                                                         
@@ -2571,138 +3111,120 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 }
 
 
 }
 
 
-/************************* Function: class_findmethod **************************
-       
-       Searches a 'classinfo' structure for a method having the given name and
-       type and returns the index in the class info structure.
-       If type is NULL, it is ignored.
+/****************** Function: class_resolvefield_int ***************************
+
+    This is an internally used helper function. Do not use this directly.
+
+       Tries to resolve a field having the given name and type.
+    If the field cannot be resolved, NULL is returned.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
 {
        s4 i;
-#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
-       char *buffer;                   
-       int buffer_len, pos;
-#endif
-#ifdef JOWENN_DEBUG1
+       fieldinfo *fi;
 
 
-       buffer_len = 
-               utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
-       
-       buffer = MNEW(char, buffer_len);
+       /* search for field in class c */
+       for (i = 0; i < c->fieldscount; i++) { 
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+                       return &(c->fields[i]);
+               }
+    }
 
 
-       strcpy(buffer, "class_findmethod: method:");
-       utf_sprint(buffer + strlen(buffer), name);
-       strcpy(buffer + strlen(buffer), ", desc: ");
-       utf_sprint(buffer + strlen(buffer), desc);
-       strcpy(buffer + strlen(buffer), ", classname: ");
-       utf_sprint(buffer + strlen(buffer), c->name);
-       
-       log_text(buffer);       
+       /* try superinterfaces recursively */
+       for (i = 0; i < c->interfacescount; ++i) {
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+               if (fi)
+                       return fi;
+       }
 
 
-       MFREE(buffer, char, buffer_len);
-#endif 
-       for (i = 0; i < c->methodscount; i++) {
-#ifdef JOWENN_DEBUG2
-               buffer_len = 
-                       utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
+       /* try superclass */
+       if (c->super)
+               return class_resolvefield_int(c->super, name, desc);
+
+       /* not found */
+       return NULL;
+}
+
+
+/********************* Function: class_resolvefield ***************************
        
        
-               buffer = MNEW(char, buffer_len);
+       Resolves a reference from REFERER to a field with NAME and DESC in class C.
+
+    If the field cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
 
 
-               strcpy(buffer, "class_findmethod: comparing to method:");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].name);
-               strcpy(buffer + strlen(buffer), ", desc: ");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
+                                                         classinfo *referer, bool except)
+{
+       fieldinfo *fi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
        
        
-               log_text(buffer);       
+       fi = class_resolvefield_int(c, name, desc);
 
 
-               MFREE(buffer, char, buffer_len);
-#endif 
-               
-               
-               if ((c->methods[i].name == name) && ((desc == NULL) ||
-                                                                                        (c->methods[i].descriptor == desc))) {
-                       return i;
-               }
+       if (!fi) {
+               if (except)
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
+                                                                                name);
+
+               return NULL;
        }
 
        }
 
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
+       /* XXX check access rights */
 
 
-       return -1;
+       return fi;
 }
 
 
 /************************* Function: class_findmethod **************************
        
        Searches a 'classinfo' structure for a method having the given name and
 }
 
 
 /************************* Function: class_findmethod **************************
        
        Searches a 'classinfo' structure for a method having the given name and
-       type.
+       type and returns the index in the class info structure.
        If type is NULL, it is ignored.
 
 *******************************************************************************/
 
        If type is NULL, it is ignored.
 
 *******************************************************************************/
 
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
 {
 {
-#if 0
        s4 i;
        s4 i;
-#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
-       char *buffer;                   
-       int buffer_len, pos;
-#endif
-#ifdef JOWENN_DEBUG1
 
 
-       buffer_len = 
-               utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
-       
-       buffer = MNEW(char, buffer_len);
-
-       strcpy(buffer, "class_findmethod: method:");
-       utf_sprint(buffer + strlen(buffer), name);
-       strcpy(buffer + strlen(buffer), ", desc: ");
-       utf_sprint(buffer + strlen(buffer), desc);
-       strcpy(buffer + strlen(buffer), ", classname: ");
-       utf_sprint(buffer + strlen(buffer), c->name);
-       
-       log_text(buffer);       
-
-       MFREE(buffer, char, buffer_len);
-#endif 
        for (i = 0; i < c->methodscount; i++) {
        for (i = 0; i < c->methodscount; i++) {
-#ifdef JOWENN_DEBUG2
-               buffer_len = 
-                       utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
-       
-               buffer = MNEW(char, buffer_len);
 
 
-               strcpy(buffer, "class_findmethod: comparing to method:");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].name);
-               strcpy(buffer + strlen(buffer), ", desc: ");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
-       
-               log_text(buffer);       
+/*             utf_display_classname(c->name);printf("."); */
+/*             utf_display(c->methods[i].name);printf("."); */
+/*             utf_display(c->methods[i].descriptor); */
+/*             printf("\n"); */
 
 
-               MFREE(buffer, char, buffer_len);
-#endif 
-               
                if ((c->methods[i].name == name) && ((desc == NULL) ||
                                                                                         (c->methods[i].descriptor == desc))) {
                if ((c->methods[i].name == name) && ((desc == NULL) ||
                                                                                         (c->methods[i].descriptor == desc))) {
-                       return &(c->methods[i]);
+                       return i;
                }
        }
                }
        }
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
-       return NULL;
-#endif
 
 
-       s4 idx=class_findmethodIndex(c, name, desc);
-/*     if (idx==-1) log_text("class_findmethod: method not found");*/
-       if (idx == -1) return NULL;
+       return -1;
+}
+
+
+/************************* Function: class_findmethod **************************
+       
+       Searches a 'classinfo' structure for a method having the given name and
+       type.
+       If type is NULL, it is ignored.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+{
+       s4 idx = class_findmethodIndex(c, name, desc);
+
+       if (idx == -1)
+               return NULL;
 
        return &(c->methods[idx]);
 }
 
        return &(c->methods[idx]);
 }
@@ -2717,6 +3239,7 @@ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
 {
        methodinfo *mi;
 methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
 {
        methodinfo *mi;
+
        mi = class_findmethod(c, name, desc);
 
        if (!mi) {
        mi = class_findmethod(c, name, desc);
 
        if (!mi) {
@@ -2835,20 +3358,168 @@ methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
 
 /************************* Function: class_resolvemethod ***********************
        
 
 /************************* Function: class_resolvemethod ***********************
        
-       Searches a class and every super class for a method.
+       Searches a class and every super class for a method.
+
+*******************************************************************************/
+
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+{
+       /*log_text("Trying to resolve a method");
+       utf_display(c->name);
+       utf_display(name);
+       utf_display(desc);*/
+
+       while (c) {
+               /*log_text("Looking in:");
+               utf_display(c->name);*/
+               methodinfo *m = class_findmethod(c, name, desc);
+               if (m) return m;
+               /* search superclass */
+               c = c->super;
+       }
+       /*log_text("method not found:");*/
+
+       return NULL;
+}
+
+
+/****************** Function: class_resolveinterfacemethod_int ****************
+
+    Internally used helper function. Do not use this directly.
+
+*******************************************************************************/
+
+static
+methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
+{
+       methodinfo *mi;
+       int i;
+       
+       mi = class_findmethod(c,name,desc);
+       if (mi)
+               return mi;
+
+       /* try the superinterfaces */
+       for (i=0; i<c->interfacescount; ++i) {
+               mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
+               if (mi)
+                       return mi;
+       }
+       
+       return NULL;
+}
+
+/******************** Function: class_resolveinterfacemethod ******************
+
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    interface C.
+
+    If the method cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+                                                                                classinfo *referer, bool except)
+{
+       methodinfo *mi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+       if (!(c->flags & ACC_INTERFACE)) {
+               if (except)
+                       *exceptionptr =
+                               new_exception(string_java_lang_IncompatibleClassChangeError);
+
+               return NULL;
+       }
+
+       mi = class_resolveinterfacemethod_int(c, name, desc);
+
+       if (mi)
+               return mi;
+
+       /* try class java.lang.Object */
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+
+       if (mi)
+               return mi;
+
+       if (except)
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
+
+       return NULL;
+}
+
+
+/********************* Function: class_resolveclassmethod *********************
+       
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    class C.
+
+    If the method cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+                                                                        classinfo *referer, bool except)
+{
+       classinfo *cls;
+       methodinfo *mi;
+       s4 i;
+       char msg[MAXLOGTEXT];
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+/*     if (c->flags & ACC_INTERFACE) { */
+/*             if (except) */
+/*                     *exceptionptr = */
+/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
+/*             return NULL; */
+/*     } */
+
+       /* try class c and its superclasses */
+       cls = c;
+       do {
+               mi = class_findmethod(cls, name, desc);
+               if (mi)
+                       goto found;
+       } while ((cls = cls->super) != NULL); /* try the superclass */
+
+       /* try the superinterfaces */
+       for (i = 0; i < c->interfacescount; ++i) {
+               mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
+               if (mi)
+                       goto found;
+       }
+       
+       if (except) {
+               utf_sprint(msg, c->name);
+               sprintf(msg + strlen(msg), ".");
+               utf_sprint(msg + strlen(msg), name);
+               utf_sprint(msg + strlen(msg), desc);
+
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, msg);
+       }
 
 
-*******************************************************************************/
+       return NULL;
 
 
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
-{
-       while (c) {
-               methodinfo *m = class_findmethod(c, name, desc);
-               if (m) return m;
-               /* search superclass */
-               c = c->super;
+ found:
+       if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+               if (except)
+                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+
+               return NULL;
        }
 
        }
 
-       return NULL;
+       /* XXX check access rights */
+
+       return mi;
 }
 
 
 }
 
 
@@ -2876,74 +3547,143 @@ bool class_issubclass(classinfo *sub, classinfo *super)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void class_init(classinfo *c)
+static classinfo *class_init_intern(classinfo *c);
+
+classinfo *class_init(classinfo *c)
+{
+       classinfo *r;
+
+       if (!makeinitializations)
+               return c;
+
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
+
+       /* maybe the class is already initalized or the current thread, which can
+          pass the monitor, is currently initalizing this class */
+
+       if (c->initialized || c->initializing) {
+               builtin_monitorexit((java_objectheader *) c);
+
+               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;
+
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+
+       return r;
+}
+
+
+/* this function MUST NOT be called directly, because of thread <clinit>
+   race conditions */
+
+static classinfo *class_init_intern(classinfo *c)
 {
        methodinfo *m;
 {
        methodinfo *m;
-       native_stackframeinfo **info;
        s4 i;
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        int b;
 #endif
 
        s4 i;
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        int b;
 #endif
 
-       if (!makeinitializations)
-               return;
-       if (c->initialized)
-               return;
+       if (!c->loaded)
+               if (!class_load(c))
+                       return NULL;
 
 
-       c->initialized = true;
+       if (!c->linked)
+               if (!class_link(c))
+                       return NULL;
 
 
-#ifdef STATISTICS
-       count_class_inits++;
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_class_inits++;
 #endif
 
        /* initialize super class */
        if (c->super) {
 #endif
 
        /* initialize super class */
        if (c->super) {
-               if (initverbose) {
-                       char logtext[MAXLOGTEXT];
-                       sprintf(logtext, "Initialize super class ");
-                       utf_sprint(logtext + strlen(logtext), c->super->name);
-                       sprintf(logtext + strlen(logtext), " from ");
-                       utf_sprint(logtext + strlen(logtext), c->name);
-                       log_text(logtext);
+               if (!c->super->loaded)
+                       if (!class_load(c->super))
+                               return NULL;
+
+               if (!c->super->linked)
+                       if (!class_link(c->super))
+                               return NULL;
+
+               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;
                }
                }
-               class_init(c->super);
        }
 
        /* initialize interface classes */
        for (i = 0; i < c->interfacescount; i++) {
        }
 
        /* initialize interface classes */
        for (i = 0; i < c->interfacescount; i++) {
-               if (initverbose) {
-                       char logtext[MAXLOGTEXT];
-                       sprintf(logtext, "Initialize interface class ");
-                       utf_sprint(logtext + strlen(logtext), c->interfaces[i]->name);
-                       sprintf(logtext + strlen(logtext), " from ");
-                       utf_sprint(logtext + strlen(logtext), c->name);
-                       log_text(logtext);
+               if (!c->interfaces[i]->loaded)
+                       if (!class_load(c->interfaces[i]))
+                               return NULL;
+
+               if (!c->interfaces[i]->linked)
+                       if (!class_link(c->interfaces[i]))
+                               return NULL;
+
+               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;
                }
                }
-               class_init(c->interfaces[i]);  /* real */
        }
 
        m = class_findmethod(c, utf_clinit, utf_fidesc);
        }
 
        m = class_findmethod(c, utf_clinit, utf_fidesc);
+
        if (!m) {
                if (initverbose) {
                        char logtext[MAXLOGTEXT];
                        sprintf(logtext, "Class ");
        if (!m) {
                if (initverbose) {
                        char logtext[MAXLOGTEXT];
                        sprintf(logtext, "Class ");
-                       utf_sprint(logtext + strlen(logtext), c->name);
-                       sprintf(logtext + strlen(logtext), " has no initializer");
+                       utf_sprint_classname(logtext + strlen(logtext), c->name);
+                       sprintf(logtext + strlen(logtext), " has no static class initializer");
                        log_text(logtext);
                }
                        log_text(logtext);
                }
-               /*              goto callinitialize;*/
-               return;
+
+               return c;
        }
 
        if (!(m->flags & ACC_STATIC))
                panic("Class initializer is not static!");
 
        }
 
        if (!(m->flags & ACC_STATIC))
                panic("Class initializer is not static!");
 
-       if (initverbose) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Starting initializer for class: ");
-               utf_sprint(logtext + strlen(logtext), c->name);
-               log_text(logtext);
-       }
+       if (initverbose)
+               log_message_class("Starting static class initializer for class: ", c);
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        b = blockInts;
 
 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        b = blockInts;
@@ -2958,59 +3698,42 @@ void class_init(classinfo *c)
        blockInts = b;
 #endif
 
        blockInts = b;
 #endif
 
-       /* we have to throw an exception */
+       /* we have an exception or error */
        if (*exceptionptr) {
        if (*exceptionptr) {
-               printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
-               printf("Caused by: ");
-               utf_display((*exceptionptr)->vftbl->class->name);
-               printf("\n");
-               fflush(stdout);
-               exit(1);
-       }
+               /* is this an exception, than wrap it */
+               if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
+                       java_objectheader *xptr;
+                       java_objectheader *cause;
 
 
-       if (initverbose) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Finished initializer for class: ");
-               utf_sprint(logtext + strlen(logtext), c->name);
-               log_text(logtext);
-       }
+                       /* class is NOT initialized */
+                       c->initialized = false;
 
 
-       if (c->name == utf_systemclass) {
-               /* class java.lang.System requires explicit initialization */
+                       /* get the cause */
+                       cause = *exceptionptr;
 
 
-               if (initverbose)
-                       printf("#### Initializing class System");
+                       /* clear exception, because we are calling jit code again */
+                       *exceptionptr = NULL;
 
 
-                /* find initializing method */
-               m = class_findmethod(c,
-                                                        utf_initsystemclass,
-                                                        utf_fidesc);
+                       /* wrap the exception */
+                       xptr =
+                               new_exception_throwable(string_java_lang_ExceptionInInitializerError,
+                                                                               (java_lang_Throwable *) cause);
 
 
-               if (!m) {
-                       /* no method found */
-                       /* printf("initializeSystemClass failed"); */
-                       return;
-               }
+                       /* XXX should we exit here? */
+                       if (*exceptionptr)
+                               throw_exception();
 
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-               b = blockInts;
-               blockInts = 0;
-#endif
+                       /* set new exception */
+                       *exceptionptr = xptr;
+               }
 
 
-               asm_calljavafunction(m, NULL, NULL, NULL, NULL);
+               return NULL;
+       }
 
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-               assert(blockInts == 0);
-               blockInts = b;
-#endif
+       if (initverbose)
+               log_message_class("Finished static class initializer for class: ", c);
 
 
-               if (*exceptionptr) {
-                       printf("#### initializeSystemClass has thrown: ");
-                       utf_display((*exceptionptr)->vftbl->class->name);
-                       printf("\n");
-                       fflush(stdout);
-               }
-       }
+       return c;
 }
 
 
 }
 
 
@@ -3263,205 +3986,52 @@ void class_showmethods (classinfo *c)
 }
 
 
 }
 
 
-
 /******************************************************************************/
 /******************* General functions for the class loader *******************/
 /******************************************************************************/
 
 /******************************************************************************/
 /******************* General functions for the class loader *******************/
 /******************************************************************************/
 
-/********************* Function: loader_load ***********************************
-
-       Loads and links the class desired class and each class and interface
-       referenced by it.
-       Returns: a pointer to this class
-
-*******************************************************************************/
-
-static int loader_load_running = 0;
-
-classinfo *loader_load(utf *topname)
-{
-       classinfo *top;
-       classinfo *c;
-       s8 starttime = 0;
-       s8 stoptime = 0;
-       classinfo *notlinkable;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_lock(&compiler_mutex);
-#endif
-
-       /* avoid recursive calls */
-       if (loader_load_running)
-               return class_new(topname);
-
-       loader_load_running++;
-       
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsDisable();
-#endif
-
-       if (getloadingtime)
-               starttime = getcputime();
-
-       top = class_new(topname);
-
-       /* load classes */
-       while ((c = list_first(&unloadedclasses))) {
-               if (!class_load(c)) {
-                       if (linkverbose)
-                               dolog("Failed to load class");
-                       list_remove(&unloadedclasses, c);
-                       top = NULL;
-               }
-       }
-
-       /* link classes */
-       if (linkverbose)
-               dolog("Linking...");
-
-       /* Added a hack to break infinite linking loops. A better
-        * linking algorithm would be nice. -Edwin */
-       notlinkable = NULL;
-       while ((c = list_first(&unlinkedclasses))) {
-               class_link(c);
-               if (!c->linked) {
-                       if (!notlinkable)
-                               notlinkable = c;
-                       else if (notlinkable == c) {
-                               /* We tried to link this class for the second time and
-                                * no other classes were linked in between, so we are
-                                * caught in a loop.
-                                */
-                               if (linkverbose)
-                                       dolog("Cannot resolve linking dependencies");
-                               top = NULL;
-                               if (!*exceptionptr)
-                                       throw_linkageerror_message(c->name);
-                               break;
-                       }
-
-               } else
-                       notlinkable = NULL;
-       }
-       if (linkverbose)
-               dolog("Linking done.");
-
-       if (loader_inited)
-               loader_compute_subclasses();
-
-       /* measure time */
-       if (getloadingtime) {
-               stoptime = getcputime();
-               loadingtime += (stoptime - starttime);
-       }
-
-
-       loader_load_running--;
-       
-       /* check if a former loader_load call tried to load/link the class and 
-          failed. This is needed because the class didn't appear in the 
-          undloadclasses or unlinkedclasses list during this class. */
-       if (top) {
-               if (!top->loaded) {
-                       if (linkverbose) dolog("Failed to load class (former call)");
-                       throw_noclassdeffounderror_message(top->name);
-                       top = NULL;
-                       
-               } else if (!top->linked) {
-                       if (linkverbose)
-                               dolog("Failed to link class (former call)");
-                       throw_linkageerror_message(top->name);
-                       top = NULL;
-               }
-       }
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsRestore();
-#endif
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
-#endif
-
-       /* DEBUG */ /*if (linkverbose && !top) dolog("returning NULL from loader_load");*/
-       
-       return top; 
-}
-
-
-/****************** Function: loader_load_sysclass ****************************
-
-       Loads and links the class desired class and each class and interface
-       referenced by it.
-
-    The pointer to the classinfo is stored in *top if top != NULL.
-    The pointer is also returned.
-
-    If the class could not be loaded the function aborts with an error.
-
-*******************************************************************************/
-
-classinfo *loader_load_sysclass(classinfo **top, utf *topname)
-{
-       classinfo *cls;
-
-       if ((cls = loader_load(topname)) == NULL) {
-               log_plain("Could not load important system class: ");
-               log_plain_utf(topname);
-               log_nl();
-               panic("Could not load important system class");
-       }
-
-       if (top) *top = cls;
-
-       return cls;
-}
-
-
 /**************** function: create_primitive_classes ***************************
 
 /**************** function: create_primitive_classes ***************************
 
-       create classes representing primitive types 
-
-********************************************************************************/
+       create classes representing primitive types
 
 
+*******************************************************************************/
 
 void create_primitive_classes()
 {  
        int i;
 
 
 void create_primitive_classes()
 {  
        int i;
 
-       for (i=0;i<PRIMITIVETYPE_COUNT;i++) {
+       for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
                /* create primitive class */
                /* create primitive class */
-               classinfo *c = class_new ( utf_new_char(primitivetype_table[i].name) );
-                c -> classUsed = NOTUSED; /* not used initially CO-RT */               
-               c -> impldBy = NULL;
+               classinfo *c =
+                       class_new_intern(utf_new_char(primitivetype_table[i].name));
+               c->classUsed = NOTUSED; /* not used initially CO-RT */
+               c->impldBy = NULL;
                
                /* prevent loader from loading primitive class */
                
                /* prevent loader from loading primitive class */
-               list_remove (&unloadedclasses, c);
-               c->loaded=true;
-               /* add to unlinked classes */
-               list_addlast (&unlinkedclasses, c);             
-/*JOWENN primitive types don't have objects as super class             c -> super = class_java_lang_Object; */
-               class_link (c);
+               c->loaded = true;
+               class_link(c);
 
                primitivetype_table[i].class_primitive = c;
 
                /* create class for wrapping the primitive type */
 
                primitivetype_table[i].class_primitive = c;
 
                /* create class for wrapping the primitive type */
-               primitivetype_table[i].class_wrap =
-                       class_new( utf_new_char(primitivetype_table[i].wrapname) );
-                primitivetype_table[i].class_wrap -> classUsed = NOTUSED; /* not used initially CO-RT */
-               primitivetype_table[i].class_wrap  -> impldBy = NULL;
+               c = class_new_intern(utf_new_char(primitivetype_table[i].wrapname));
+               primitivetype_table[i].class_wrap = c;
+               primitivetype_table[i].class_wrap->classUsed = NOTUSED; /* not used initially CO-RT */
+               primitivetype_table[i].class_wrap->impldBy = NULL;
 
                /* create the primitive array class */
                if (primitivetype_table[i].arrayname) {
 
                /* create the primitive array class */
                if (primitivetype_table[i].arrayname) {
-                       c = class_new( utf_new_char(primitivetype_table[i].arrayname) );
+                       c = class_new_intern(utf_new_char(primitivetype_table[i].arrayname));
                        primitivetype_table[i].arrayclass = c;
                        primitivetype_table[i].arrayclass = c;
-                       c->loaded=true;
-                       if (!c->linked) class_link(c);
+                       c->loaded = true;
+                       if (!c->linked)
+                               class_link(c);
                        primitivetype_table[i].arrayvftbl = c->vftbl;
                }
        }
 }
 
                        primitivetype_table[i].arrayvftbl = c->vftbl;
                }
        }
 }
 
+
 /**************** function: class_primitive_from_sig ***************************
 
        return the primitive class indicated by the given signature character
 /**************** function: class_primitive_from_sig ***************************
 
        return the primitive class indicated by the given signature character
@@ -3527,7 +4097,7 @@ classinfo *class_primitive_from_sig(char sig)
                             * CLASSLOAD_PANIC....abort execution with an error message
                    CLASSLOAD_NOPANIC..return NULL on error
 
                             * 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)
 
 classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                                                                 char **next, int mode)
@@ -3536,7 +4106,7 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
        bool error = false;
        utf *name;
 
        bool error = false;
        utf *name;
 
-       SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
+       SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
 
        if (mode & CLASSLOAD_CHECKEND)
                error |= (utf_ptr != end_ptr);
 
        if (mode & CLASSLOAD_CHECKEND)
                error |= (utf_ptr != end_ptr);
@@ -3567,9 +4137,20 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                          /* FALLTHROUGH! */
                  case '[':
                          if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
                          /* FALLTHROUGH! */
                  case '[':
                          if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
-                         name = utf_new(start,utf_ptr-start);
-                         return (mode & CLASSLOAD_LOAD)
-                                 ? loader_load(name) : class_new(name); /* XXX handle errors */
+                         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 */
+                         }
                }
        }
 
                }
        }
 
@@ -3578,7 +4159,7 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                return NULL;
 
        log_plain("Invalid descriptor at beginning of '");
                return NULL;
 
        log_plain("Invalid descriptor at beginning of '");
-       log_plain_utf(utf_new(start, end_ptr-start));
+       log_plain_utf(utf_new(start, end_ptr - start));
        log_plain("'");
        log_nl();
                                                  
        log_plain("'");
        log_nl();
                                                  
@@ -3631,80 +4212,6 @@ int type_from_descriptor(classinfo **cls, char *utf_ptr, char *end_ptr,
 }
 
 
 }
 
 
-
-/*************** function: create_system_exception_classes *******************************
-
-       create system exception classes needed by default 
-
-********************************************************************************/
-
-static void create_system_exception_classes()
-{
-
-       if (verbose) log_text("loader_init:  create_system_exception_classs: loader_load: java/lang/ClassCastException");
-       loader_load_sysclass(&class_java_lang_ClassCastException,
-                                                utf_new_char ("java/lang/ClassCastException"));
-       loader_load_sysclass(&class_java_lang_NullPointerException,
-                                                utf_new_char ("java/lang/NullPointerException"));
-       loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
-                                                utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
-       loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
-                                                utf_new_char ("java/lang/NegativeArraySizeException"));
-       loader_load_sysclass(&class_java_lang_OutOfMemoryError,
-                                                utf_new_char ("java/lang/OutOfMemoryError"));
-       loader_load_sysclass(&class_java_lang_ArrayStoreException,
-                                                utf_new_char ("java/lang/ArrayStoreException"));
-       loader_load_sysclass(&class_java_lang_ArithmeticException,
-                                                utf_new_char ("java/lang/ArithmeticException"));
-       loader_load_sysclass(&class_java_lang_ThreadDeath,
-                                                utf_new_char ("java/lang/ThreadDeath"));
-
-
-}
-
-
-/*************** function: create_system_exception_classes *******************************
-
-       create system exception proto classes needed by default 
-
-********************************************************************************/
-
-static void create_system_exception_proto_classes()
-{
-
-       if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
-       proto_java_lang_ClassCastException =
-               builtin_new(class_java_lang_ClassCastException);
-
-       if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
-
-       proto_java_lang_NullPointerException =
-               builtin_new(class_java_lang_NullPointerException);
-       if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
-
-       proto_java_lang_ArrayIndexOutOfBoundsException =
-               builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
-
-       proto_java_lang_NegativeArraySizeException =
-               builtin_new(class_java_lang_NegativeArraySizeException);
-
-       proto_java_lang_OutOfMemoryError =
-               builtin_new(class_java_lang_OutOfMemoryError);
-
-       proto_java_lang_ArithmeticException =
-               builtin_new(class_java_lang_ArithmeticException);
-
-       proto_java_lang_ArrayStoreException =
-               builtin_new(class_java_lang_ArrayStoreException);
-
-       proto_java_lang_ThreadDeath =
-               builtin_new(class_java_lang_ThreadDeath);
-
-
-}
-
-
-
 /*************** function: create_pseudo_classes *******************************
 
        create pseudo classes used by the typechecker
 /*************** function: create_pseudo_classes *******************************
 
        create pseudo classes used by the typechecker
@@ -3715,39 +4222,32 @@ static void create_pseudo_classes()
 {
     /* pseudo class for Arraystubs (extends java.lang.Object) */
     
 {
     /* pseudo class for Arraystubs (extends java.lang.Object) */
     
-    pseudo_class_Arraystub = class_new(utf_new_char("$ARRAYSTUB$"));
-    list_remove(&unloadedclasses, pseudo_class_Arraystub);
-
+    pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
+       pseudo_class_Arraystub->loaded = true;
     pseudo_class_Arraystub->super = class_java_lang_Object;
     pseudo_class_Arraystub->interfacescount = 2;
     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
 
     pseudo_class_Arraystub->super = class_java_lang_Object;
     pseudo_class_Arraystub->interfacescount = 2;
     pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
     pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
     pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
 
-    list_addlast(&unlinkedclasses, pseudo_class_Arraystub);
     class_link(pseudo_class_Arraystub);
 
        pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
 
     /* pseudo class representing the null type */
     
     class_link(pseudo_class_Arraystub);
 
        pseudo_class_Arraystub_vftbl = pseudo_class_Arraystub->vftbl;
 
     /* pseudo class representing the null type */
     
-    pseudo_class_Null = class_new(utf_new_char("$NULL$"));
-    list_remove(&unloadedclasses, pseudo_class_Null);
-
+       pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
+       pseudo_class_Null->loaded = true;
     pseudo_class_Null->super = class_java_lang_Object;
     pseudo_class_Null->super = class_java_lang_Object;
-
-    list_addlast(&unlinkedclasses, pseudo_class_Null);
-    class_link(pseudo_class_Null);     
+       class_link(pseudo_class_Null);  
 
     /* pseudo class representing new uninitialized objects */
     
 
     /* pseudo class representing new uninitialized objects */
     
-    pseudo_class_New = class_new(utf_new_char("$NEW$"));
-    list_remove(&unloadedclasses, pseudo_class_New);
-
-    pseudo_class_New->super = class_java_lang_Object;
-
-    list_addlast(&unlinkedclasses, pseudo_class_New);
-    class_link(pseudo_class_New);      
+       pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
+       pseudo_class_New->loaded = true;
+       pseudo_class_New->linked = true;
+       pseudo_class_New->super = class_java_lang_Object;
+/*     class_link(pseudo_class_New); */
 }
 
 
 }
 
 
@@ -3762,16 +4262,13 @@ void loader_init(u1 *stackbottom)
 {
        interfaceindex = 0;
        
 {
        interfaceindex = 0;
        
-       list_init(&unloadedclasses, OFFSET(classinfo, listnode));
-       list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
-       list_init(&linkedclasses, OFFSET(classinfo, listnode));
-
        /* create utf-symbols for pointer comparison of frequently used strings */
        utf_innerclasses    = utf_new_char("InnerClasses");
        utf_constantvalue   = utf_new_char("ConstantValue");
        /* create utf-symbols for pointer comparison of frequently used strings */
        utf_innerclasses    = utf_new_char("InnerClasses");
        utf_constantvalue   = utf_new_char("ConstantValue");
-       utf_code                = utf_new_char("Code");
-       utf_exceptions          = utf_new_char("Exceptions");
-       utf_linenumbertable     = utf_new_char("LineNumberTable");
+       utf_code            = utf_new_char("Code");
+       utf_exceptions      = utf_new_char("Exceptions");
+       utf_linenumbertable = utf_new_char("LineNumberTable");
+       utf_sourcefile      = utf_new_char("SourceFile");
        utf_finalize        = utf_new_char("finalize");
        utf_fidesc              = utf_new_char("()V");
        utf_init                = utf_new_char("<init>");
        utf_finalize        = utf_new_char("finalize");
        utf_fidesc              = utf_new_char("()V");
        utf_init                = utf_new_char("<init>");
@@ -3781,31 +4278,35 @@ void loader_init(u1 *stackbottom)
        utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
        utf_initialize      = utf_new_char("initialize");
        utf_initializedesc  = utf_new_char("(I)V");
        utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
        utf_initialize      = utf_new_char("initialize");
        utf_initializedesc  = utf_new_char("(I)V");
-
        utf_vmclass         = utf_new_char("java/lang/VMClass");
        utf_java_lang_Object= utf_new_char("java/lang/Object");
        utf_vmclass         = utf_new_char("java/lang/VMClass");
        utf_java_lang_Object= utf_new_char("java/lang/Object");
-
        array_packagename   = utf_new_char("<the array package>");
        array_packagename   = utf_new_char("<the array package>");
+       utf_fillInStackTrace_name = utf_new_char("fillInStackTrace");
+       utf_fillInStackTrace_desc = utf_new_char("()Ljava/lang/Throwable;");
 
        /* create some important classes */
        /* These classes have to be created now because the classinfo
         * pointers are used in the loading code.
         */
 
        /* create some important classes */
        /* These classes have to be created now because the classinfo
         * pointers are used in the loading code.
         */
-       class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
-       class_java_lang_String = class_new(utf_new_char("java/lang/String"));
-       class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
-       class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
-
-       if (verbose) log_text("loader_init: java/lang/Object");
-       /* load the classes which were created above */
-       loader_load_sysclass(NULL, class_java_lang_Object->name);
-
-       loader_inited = 1; /*JOWENN*/
-
-       loader_load_sysclass(&class_java_lang_Throwable,
-                                                utf_new_char("java/lang/Throwable"));
-
-        create_system_exception_classes();
+       class_java_lang_Object =
+               class_new_intern(utf_java_lang_Object);
+       class_load(class_java_lang_Object);
+       class_link(class_java_lang_Object);
+
+       class_java_lang_String =
+               class_new_intern(utf_new_char("java/lang/String"));
+       class_load(class_java_lang_String);
+       class_link(class_java_lang_String);
+
+       class_java_lang_Cloneable =
+               class_new_intern(utf_new_char("java/lang/Cloneable"));
+       class_load(class_java_lang_Cloneable);
+       class_link(class_java_lang_Cloneable);
+
+       class_java_io_Serializable =
+               class_new_intern(utf_new_char("java/io/Serializable"));
+       class_load(class_java_io_Serializable);
+       class_link(class_java_io_Serializable);
 
        /* create classes representing primitive types */
        create_primitive_classes();
 
        /* create classes representing primitive types */
        create_primitive_classes();
@@ -3816,49 +4317,11 @@ void loader_init(u1 *stackbottom)
        /* correct vftbl-entries (retarded loading of class java/lang/String) */
        stringtable_update();
 
        /* correct vftbl-entries (retarded loading of class java/lang/String) */
        stringtable_update();
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       if (stackbottom!=0)
+#if defined(USE_THREADS)
+       if (stackbottom != 0)
                initLocks();
                initLocks();
-#endif
-        create_system_exception_proto_classes();
-
-       loader_inited = 1;
-}
-
-
-/********************* Function: loader_initclasses ****************************
-
-       Initializes all loaded but uninitialized classes
-
-*******************************************************************************/
-
-#if 0
-/* XXX TWISTI: i think we do not need this */
-void loader_initclasses ()
-{
-       classinfo *c;
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_lock(&compiler_mutex);
-#endif
-
-       intsDisable();                     /* schani */
-
-       if (makeinitializations) {
-               c = list_first(&linkedclasses);
-               while (c) {
-                       class_init(c);
-                       c = list_next(&linkedclasses, c);
-               }
-       }
-
-       intsRestore();                      /* schani */
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
 #endif
 }
 #endif
 }
-#endif
 
 
 static void loader_compute_class_values(classinfo *c)
 
 
 static void loader_compute_class_values(classinfo *c)
@@ -3872,73 +4335,48 @@ static void loader_compute_class_values(classinfo *c)
                loader_compute_class_values(subs);
                subs = subs->nextsub;
        }
                loader_compute_class_values(subs);
                subs = subs->nextsub;
        }
+
        c->vftbl->diffval = classvalue - c->vftbl->baseval;
        c->vftbl->diffval = classvalue - c->vftbl->baseval;
-       
-/*     
-       {
-       int i;
-       for (i = 0; i < c->index; i++)
-               printf(" ");
-       printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
-       utf_display(c->name);
-       printf("\n");
-       }
-*/     
 }
 
 
 }
 
 
-void loader_compute_subclasses()
+void loader_compute_subclasses(classinfo *c)
 {
 {
-       classinfo *c;
-       
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsDisable();                     /* schani */
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+#else
+       intsDisable();
+#endif
 #endif
 
 #endif
 
-       c = list_first(&linkedclasses);
-       while (c) {
-               if (!(c->flags & ACC_INTERFACE)) {
-                       c->nextsub = 0;
-                       c->sub = 0;
-               }
-               c = list_next(&linkedclasses, c);
+       if (!(c->flags & ACC_INTERFACE)) {
+               c->nextsub = 0;
+               c->sub = 0;
        }
 
        }
 
-       c = list_first(&linkedclasses);
-       while (c) {
-               if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
-                       c->nextsub = c->super->sub;
-                       c->super->sub = c;
-               }
-               c = list_next(&linkedclasses, c);
+       if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
+               c->nextsub = c->super->sub;
+               c->super->sub = c;
        }
 
        classvalue = 0;
        }
 
        classvalue = 0;
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       cast_lock();
-#endif
-       loader_compute_class_values(class_java_lang_Object);
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       cast_unlock();
-#endif
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsRestore();                      /* schani */
-#endif
-}
-
 
 
-/******************** function classloader_buffer ******************************
-    sets buffer for reading classdata
+       /* this is the java.lang.Object special case */
+       if (!class_java_lang_Object) {
+               loader_compute_class_values(c);
 
 
-*******************************************************************************/
+       } else {
+               loader_compute_class_values(class_java_lang_Object);
+       }
 
 
-void classload_buffer(u1 *buf, int len)
-{
-       classbuffer      = buf;
-       classbuffer_size = len;
-       classbuf_pos     = buf - 1;
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_unlock();
+#else
+       intsRestore();
+#endif
+#endif
 }
 
 
 }
 
 
@@ -3951,18 +4389,15 @@ void classload_buffer(u1 *buf, int len)
 void loader_close()
 {
        classinfo *c;
 void loader_close()
 {
        classinfo *c;
+       s4 slot;
 
 
-       while ((c = list_first(&unloadedclasses))) {
-               list_remove(&unloadedclasses, c);
-               class_free(c);
-       }
-       while ((c = list_first(&unlinkedclasses))) {
-               list_remove(&unlinkedclasses, c);
-               class_free(c);
-       }
-       while ((c = list_first(&linkedclasses))) {
-               list_remove(&linkedclasses, c);
-               class_free(c);
+       for (slot = 0; slot < class_hash.size; slot++) {
+               c = class_hash.ptr[slot];
+
+               while (c) {
+                       class_free(c);
+                       c = c->hashlink;
+               }
        }
 }
 
        }
 }