Calling convention fixes.
[cacao.git] / src / vm / loader.c
index 888e4517d87f1d0a9239fa904f1a5c22ef029e3f..2a4681af59d61a9e554dc78ed3b8a0762f6fb612 100644 (file)
@@ -1,9 +1,9 @@
-/* loader.c - class loader functions
+/* vm/loader.c - class loader functions
 
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    This file is part of CACAO.
 
    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 1008 2004-03-31 20:13:14Z edwin $
+   $Id: loader.c 1936 2005-02-10 11:04:10Z twisti $
 
 */
 
 
 */
 
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
 #include <string.h>
 #include <assert.h>
 #include <sys/stat.h>
-#include "global.h"
-#include "loader.h"
-#include "main.h"
-#include "native.h"
-#include "tables.h"
-#include "builtin.h"
-#include "jit.h"
-#include "asmpart.h"
-#include "toolbox/memory.h"
-#include "toolbox/loging.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
-#include "nat/java_lang_Throwable.h"
-
-#ifdef USE_ZLIB
-#include "unzip.h"
+
+#include "mm/memory.h"
+#include "native/native.h"
+#include "native/include/java_lang_Throwable.h"
+
+#if defined(USE_THREADS)
+# if defined(NATIVE_THREADS)
+#  include "threads/native/threads.h"
+# else
+#  include "threads/green/threads.h"
+#  include "threads/green/locks.h"
+# endif
 #endif
 
 #endif
 
+#include "toolbox/logging.h"
+#include "vm/exceptions.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/stringlocal.h"
+#include "vm/tables.h"
+
+#if defined(USE_ZLIB)
+# include "vm/unzip.h"
+#endif
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+
+
 #undef JOWENN_DEBUG
 #undef JOWENN_DEBUG1
 #undef JOWENN_DEBUG2
 
 /* global variables ***********************************************************/
 
 #undef JOWENN_DEBUG
 #undef JOWENN_DEBUG1
 #undef JOWENN_DEBUG2
 
 /* 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 */
-
-static utf *utf_innerclasses;          /* InnerClasses            */
-static utf *utf_constantvalue;                 /* ConstantValue           */
-static utf *utf_code;                      /* Code                    */
-static utf *utf_exceptions;            /* Exceptions                    */
-static utf *utf_linenumbertable;               /* LineNumberTable                    */
-static utf *utf_sourcefile;            /*SourceFile*/
-static utf *utf_finalize;                  /* finalize                */
-static utf *utf_fidesc;                    /* ()V changed             */
-static utf *utf_init;                          /* <init>                  */
-static utf *utf_clinit;                    /* <clinit>                */
-static utf *utf_initsystemclass;       /* initializeSystemClass   */
-static utf *utf_systemclass;           /* java/lang/System        */
-static utf *utf_vmclassloader;      /* java/lang/VMClassLoader */
-static utf *utf_vmclass;            /* java/lang/VMClassLoader */
-static utf *utf_initialize;
-static utf *utf_initializedesc;
-static utf *utf_java_lang_Object;   /* java/lang/Object        */
-
-
-
-
-utf* clinit_desc(){
-       return utf_fidesc;
-}
-utf* clinit_name(){
-       return utf_clinit;
-}
-
-
-/* important system classes ***************************************************/
-
-classinfo *class_java_lang_Object;
-classinfo *class_java_lang_String;
-
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_lang_Cloneable;
-classinfo *class_java_io_Serializable;
-
-/* Pseudo classes for the typechecker */
-classinfo *pseudo_class_Arraystub = NULL;
-classinfo *pseudo_class_Null = NULL;
-classinfo *pseudo_class_New = NULL;
-vftbl *pseudo_class_Arraystub_vftbl = NULL;
-
-utf *array_packagename = NULL;
 
 
-static int loader_inited = 0;
+vftbl_t *pseudo_class_Arraystub_vftbl = NULL;
 
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
    ZIP/JAR archives
 ********************************************************************/
 
 
 /********************************************************************
    list of classpath entries (either filesystem directories or 
    ZIP/JAR archives
 ********************************************************************/
-static classpath_info *classpath_entries=0;
+
+static classpath_info *classpath_entries = NULL;
 
 
 /******************************************************************************
 
 
 /******************************************************************************
@@ -162,11 +118,6 @@ primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
 };
 
 
 };
 
 
-/* instances of important system classes **************************************/
-
-java_objectheader *proto_java_lang_NullPointerException;
-
-
 /************* functions for reading classdata *********************************
 
     getting classdata in blocks of variable size
 /************* functions for reading classdata *********************************
 
     getting classdata in blocks of variable size
@@ -174,114 +125,151 @@ java_objectheader *proto_java_lang_NullPointerException;
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-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                 */
+/* 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;
+}
+
 
 
-/* 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)
+/* suck_nbytes *****************************************************************
 
 
-/* transfer block of classfile data into a buffer */
+   transfer block of classfile data into a buffer
 
 
-#define suck_nbytes(buffer,len)                                                \
-       do {ASSERT_LEFT(len);                                                   \
-               memcpy(buffer,classbuf_pos+1,len);                      \
-               classbuf_pos+=len;} while (0)
+*******************************************************************************/
+
+inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+       memcpy(buffer, cb->pos + 1, len);
+       cb->pos += len;
+}
 
 
-/* skip block of classfile data */
 
 
-#define skip_nbytes(len)                                               \
-       do {ASSERT_LEFT(len);                                           \
-               classbuf_pos+=len;} while(0)
+/* skip_nbytes ****************************************************************
+
+   skip block of classfile data
+
+*******************************************************************************/
+
+inline void skip_nbytes(classbuffer *cb, s4 len)
+{
+       cb->pos += len;
+}
 
 
 
 
-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();
-       u1 b = suck_u1();
+       u1 a = suck_u1(cb);
+       u1 b = suck_u1(cb);
        return ((u2) a << 8) + (u2) b;
 }
 
 
        return ((u2) a << 8) + (u2) b;
 }
 
 
-inline u4 suck_u4()
+inline u4 suck_u4(classbuffer *cb)
 {
 {
-       u1 a = suck_u1();
-       u1 b = suck_u1();
-       u1 c = suck_u1();
-       u1 d = suck_u1();
+       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;
 }
 
        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()
-
 
 /* 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
 }
 
 
        return v;
 #endif
 }
 
 
+#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 float from classfile data */
 /* 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;
 }
@@ -293,123 +281,131 @@ static double suck_double()
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void suck_init(char *cpath)
+void suck_init(char *classpath)
 {
 {
-       char *filename=0;
        char *start;
        char *end;
        char *start;
        char *end;
-       int isZip;
-       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;
+       char *filename;
+       s4 filenamelen;
+       bool is_zip;
+       classpath_info *cpi;
+       classpath_info *lastcpi;
+
+       /* search for last classpath entry (only if there already some) */
+
+       if ((lastcpi = classpath_entries)) {
+               while (lastcpi->next)
+                       lastcpi = lastcpi->next;
+       }
+
+       for (start = classpath; (*start) != '\0';) {
+
+               /* search for ':' delimiter to get the end of the current entry */
+               for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+               if (start != end) {
+                       is_zip = false;
+                       filenamelen = end - start;
+
+                       if (filenamelen > 3) {
+                               if (strncasecmp(end - 3, "zip", 3) == 0 ||
+                                       strncasecmp(end - 3, "jar", 3) == 0) {
+                                       is_zip = true;
                                }
                                }
-#endif
                        }
                        }
-                       if (filenamelen>=(CLASSPATH_MAXFILENAME-1)) panic("path length >= MAXFILENAME in suck_init"); 
-                       if (!filename)
-                               filename=(char*)malloc(CLASSPATH_MAXFILENAME);
-                       strncpy(filename,start,filenamelen);
-                       filename[filenamelen+1]='\0';
-                       tmp=0;
-
-                       if (isZip) {
-#ifdef USE_ZLIB
-                               unzFile uf=unzOpen(filename);
+
+                       /* allocate memory for filename and fill it */
+
+                       filename = MNEW(char, filenamelen + 2);  /* 2 = "/\0" */
+                       strncpy(filename, start, filenamelen);
+                       filename[filenamelen + 1] = '\0';
+                       cpi = NULL;
+
+                       if (is_zip) {
+#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;
+                                       cpi = NEW(classpath_info);
+                                       cpi->type = CLASSPATH_ARCHIVE;
+                                       cpi->uf = uf;
+                                       cpi->next = NULL;
+                                       cpi->pd = NULL; /* ProtectionDomain not set yet */
+                                       cpi->path = filename;
                                }
                                }
+
 #else
 #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';
+                               cpi = NEW(classpath_info);
+                               cpi->type = CLASSPATH_PATH;
+                               cpi->next = NULL;
+                               cpi->pd = NULL; /* ProtectionDomain not set yet */
+
+                               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;
+
+                               cpi->path = filename;
+                               cpi->pathlen = filenamelen;
                        }
 
                        }
 
-               if (tmp) {
-                       if (insertAfter) {
-                               insertAfter->filepath.next=tmp;
-                       } else {
-                               classpath_entries=tmp;  
+                       /* attach current classpath entry */
+
+                       if (cpi) {
+                               if (!classpath_entries)
+                                       classpath_entries = cpi;
+                               else
+                                       lastcpi->next = cpi;
+
+                               lastcpi = cpi;
                        }
                        }
-                       insertAfter=tmp;
+               }
+
+               /* goto next classpath entry, skip ':' delimiter */
+
+               if ((*end) == ':') {
+                       start = end + 1;
+
+               } else {
+                       start = end;
                }
        }
                }
        }
-               if ((*end)==':') start=end+1; else start=end;
-       
-       
-       if (filename!=0) free(filename);
 }
 
 }
 
+
+void create_all_classes()
+{
+       classpath_info *cpi;
+
+       for (cpi = classpath_entries; cpi != 0; cpi = cpi->next) {
+#if defined(USE_ZLIB)
+               if (cpi->type == CLASSPATH_ARCHIVE) {
+                       cacao_entry_s *ce;
+                       unz_s *s;
+
+                       s = (unz_s *) cpi->uf;
+                       ce = s->cacao_dir_list;
+                               
+                       while (ce) {
+                               (void) class_new(ce->name);
+                               ce = ce->next;
+                       }
+
+               } else {
+#endif
+#if defined(USE_ZLIB)
+               }
+#endif
+       }
 }
 
 }
 
+
 /************************** 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
@@ -419,89 +415,135 @@ void suck_init(char *cpath)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-bool suck_start(utf *classname)
+classbuffer *suck_start(classinfo *c)
 {
 {
-       classpath_info *currPos;
-       char *utf_ptr;
-       char c;
-       char filename[CLASSPATH_MAXFILENAME+10];  /* room for '.class'                      */  
-       int  filenamelen=0;
+       classpath_info *cpi;
+/*     char *utf_ptr; */
+/*     char ch; */
+       char *filename;
+       s4    filenamelen;
+       char *path;
        FILE *classfile;
        FILE *classfile;
-       int  err;
+       bool found;
+       s4 len;
        struct stat buffer;
        struct stat buffer;
+       classbuffer *cb;
 
 
-       if (classbuffer) return true; /* classbuffer is already valid */
+       /* initialize return value */
 
 
-       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;
-       }
-       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) {
+       found = false;
+       cb = NULL;
+
+       filenamelen = utf_strlen(c->name) + 7;  /* 7 = ".class\0" */
+       filename = MNEW(char, filenamelen);
+
+       utf_sprint(filename, c->name);
+       strcat(filename, ".class");
+
+       /* walk through all classpath entries */
+
+       for (cpi = classpath_entries; cpi != NULL && cb == NULL; cpi = cpi->next) {
+#if defined(USE_ZLIB)
+               if (cpi->type == CLASSPATH_ARCHIVE) {
+
+#if defined(USE_THREADS)
+                       /* enter a monitor on zip/jar archives */
+
+                       builtin_monitorenter((java_objectheader *) cpi);
+#endif
+
+                       if (cacao_locate(cpi->uf, c->name) == UNZ_OK) {
                                unz_file_info file_info;
                                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;
-                                               /*printf("classfile size: %d\n",file_info.uncompressed_size);*/
-                                               if (unzReadCurrentFile(currPos->archive.uf, classbuffer, classbuffer_size) == classbuffer_size) {
-                                                       unzCloseCurrentFile(currPos->archive.uf);
-                                                       return true;
-                                               } else {
-                                                       MFREE(classbuffer, u1, classbuffer_size);
+
+                               if (unzGetCurrentFileInfo(cpi->uf, &file_info, filename,
+                                                                                 sizeof(filename), NULL, 0, NULL, 0) == UNZ_OK) {
+                                       if (unzOpenCurrentFile(cpi->uf) == UNZ_OK) {
+                                               cb = NEW(classbuffer);
+                                               cb->class = c;
+                                               cb->size = file_info.uncompressed_size;
+                                               cb->data = MNEW(u1, cb->size);
+                                               cb->pos = cb->data - 1;
+                                               /* We need this later in use_class_as_object to set a */
+                                               /* correct ProtectionDomain and CodeSource.           */
+                                               c->pd = (struct java_security_ProtectionDomain *) cpi; 
+
+                                               len = unzReadCurrentFile(cpi->uf, cb->data, cb->size);
+
+                                               if (len != cb->size) {
+                                                       suck_stop(cb);
                                                        log_text("Error while unzipping");
                                                        log_text("Error while unzipping");
+
+                                               } else {
+                                                       found = true;
                                                }
                                                }
-                                       } else log_text("Error while opening file in archive");
-                               } else log_text("Error while retrieving fileinfo");
-                       }
-                       unzCloseCurrentFile(currPos->archive.uf);
 
 
-               } else {
-#endif
-                       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 */
+                                       } else {
+                                               log_text("Error while opening file in archive");
+                                       }
 
 
-                               /* determine size of classfile */
+                               } else {
+                                       log_text("Error while retrieving fileinfo");
+                               }
+                       }
+                       unzCloseCurrentFile(cpi->uf);
 
 
-                               /* dolog("File: %s",filename); */
+#if defined(USE_THREADS)
+                       /* leave the monitor */
 
 
-                               err = stat(currPos->filepath.filename, &buffer);
+                       builtin_monitorexit((java_objectheader *) cpi);
+#endif
 
 
-                               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);
-                                       fclose(classfile);
-                                       return true;
+               } else {
+#endif /* USE_ZLIB */
+                       
+                       path = MNEW(char, cpi->pathlen + filenamelen + 1);
+                       strcpy(path, cpi->path);
+                       strcat(path, filename);
+
+                       classfile = fopen(path, "r");
+
+                       if (classfile) {                                   /* file exists */
+                               if (!stat(path, &buffer)) {            /* read classfile data */
+                                       cb = NEW(classbuffer);
+                                       cb->class = c;
+                                       cb->size = buffer.st_size;
+                                       cb->data = MNEW(u1, cb->size);
+                                       cb->pos = cb->data - 1;
+                                       /* We need this later in use_class_as_object to set a     */
+                                       /* correct ProtectionDomain and CodeSource.               */
+                                       c->pd = (struct java_security_ProtectionDomain *) cpi; 
+
+                                       /* read class data */
+                                       len = fread(cb->data, 1, cb->size, classfile);
+
+                                       if (len != buffer.st_size) {
+                                               suck_stop(cb);
+/*                                             if (ferror(classfile)) { */
+/*                                             } */
+
+                                       } else {
+                                               found = true;
+                                       }
                                }
                        }
                                }
                        }
-#ifdef USE_ZLIB
+
+                       MFREE(path, char, cpi->pathlen + filenamelen + 1);
+#if defined(USE_ZLIB)
                }
 #endif
        }
 
                }
 #endif
        }
 
-       if (verbose) {
-               dolog("Warning: Can not open class file '%s'", filename);
+       if (opt_verbose) {
+               if (!found)
+                       dolog("Warning: Can not open class file '%s'", filename);
        }
 
        }
 
-       return false;
+       MFREE(filename, char, filenamelen);
 
 
+       return cb;
 }
 
 }
 
+
 /************************** function suck_stop *********************************
 
        frees memory for buffer with classfile data.
 /************************** function suck_stop *********************************
 
        frees memory for buffer with classfile data.
@@ -510,24 +552,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);
 }
 
 
 }
 
 
@@ -569,61 +599,92 @@ void printflags(u2 f)
 }
 
 
 }
 
 
-/************************* Function: skipattribute *****************************
-
-       skips a (1) 'attribute' structure in the class file
+/********************** Function: skipattributebody ****************************
 
 
+       skips an attribute after the 16 bit reference to attribute_name has already
+       been read
+       
 *******************************************************************************/
 
 *******************************************************************************/
 
-static void skipattribute()
+static bool skipattributebody(classbuffer *cb)
 {
        u4 len;
 {
        u4 len;
-       suck_u2 ();
-       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;
 }
 
 
 }
 
 
-/********************** Function: skipattributebody ****************************
+/************************* Function: skipattributes ****************************
 
 
-       skips an attribute after the 16 bit reference to attribute_name has already
-       been read
+       skips num attribute structures
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void skipattributebody()
+static bool skipattributes(classbuffer *cb, u4 num)
 {
 {
+       u4 i;
        u4 len;
        u4 len;
-       len = suck_u4();
-       skip_nbytes(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: skipattributes ****************************
+/******************** 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
 
 
-       skips num attribute structures
-       
 *******************************************************************************/
 
 *******************************************************************************/
 
-static void skipattributes(u4 num)
+voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
 {
-       u4 i;
-       for (i = 0; i < num; i++)
-               skipattribute();
+       /* check index and type of constantpool entry */
+       /* (pos == 0 is caught by type comparison) */
+       if (pos >= c->cpcount || c->cptags[pos] != ctype) {
+               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               return NULL;
+       }
+
+       return c->cpinfos[pos];
 }
 
 
 /******************** function: innerclass_getconstant ************************
 
 }
 
 
 /******************** 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
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype) 
+voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* invalid position in constantpool */
 {
        /* invalid position in constantpool */
-       if (pos >= c->cpcount)
-               panic("Attempt to access constant outside range");
+       if (pos >= c->cpcount) {
+               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               return NULL;
+       }
 
        /* constantpool entry of type 0 */      
        if (!c->cptags[pos])
 
        /* constantpool entry of type 0 */      
        if (!c->cptags[pos])
@@ -631,63 +692,118 @@ voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
 
        /* check type of constantpool entry */
        if (c->cptags[pos] != ctype) {
 
        /* check type of constantpool entry */
        if (c->cptags[pos] != ctype) {
-               error("Type mismatch on constant: %d requested, %d here (innerclass_getconstant)",
-                         (int) ctype, (int) c->cptags[pos] );
+               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               return NULL;
        }
                
        return c->cpinfos[pos];
 }
 
 
        }
                
        return c->cpinfos[pos];
 }
 
 
+/********************* Function: class_constanttype ****************************
+
+       Determines the type of a class entry in the ConstantPool
+       
+*******************************************************************************/
+
+u4 class_constanttype(classinfo *c, u4 pos)
+{
+       if (pos <= 0 || pos >= c->cpcount) {
+               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               return 0;
+       }
+
+       return c->cptags[pos];
+}
+
+
 /************************ function: attribute_load ****************************
 
     read attributes from classfile
        
 *******************************************************************************/
 
 /************************ function: attribute_load ****************************
 
     read attributes from classfile
        
 *******************************************************************************/
 
-static void attribute_load(u4 num, classinfo *c)
+static bool attribute_load(classbuffer *cb, classinfo *c, u4 num)
 {
 {
+       utf *aname;
        u4 i, j;
 
        for (i = 0; i < num; i++) {
                /* retrieve attribute name */
        u4 i, j;
 
        for (i = 0; i < num; i++) {
                /* retrieve attribute name */
-               utf *aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
 
 
-               if (aname == utf_innerclasses) {
-                       /* innerclasses attribute */
+               if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                       return false;
 
 
-                       if (c->innerclass != NULL)
-                               panic("Class has more than one InnerClasses attribute");
+               if (aname == utf_InnerClasses) {
+                       /* innerclasses attribute */
+                       if (c->innerclass) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple InnerClasses attributes");
+                               return false;
+                       }
                                
                                
-                       /* skip attribute length */                                             
-                       suck_u4(); 
+                       if (!check_classbuffer_size(cb, 4 + 2))
+                               return false;
+
+                       /* skip attribute length */
+                       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;
+
+                       if (suck_u4(cb) != 2) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Wrong size for VALUE attribute");
+                               return false;
+                       }
+
+                       if (c->sourcefile) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple SourceFile attributes");
+                               return false;
                        }
                        }
-               } else if (aname==utf_sourcefile) {
-                       suck_u4();
-                       /*log_text("source file attribute found");*/
-                       c->sourcefile = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
+
+                       if (!(c->sourcefile = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                               return false;
+
                } else {
                        /* unknown attribute */
                } else {
                        /* unknown attribute */
-                       skipattributebody();
+                       if (!skipattributebody(cb))
+                               return false;
                }
        }
                }
        }
+
+       return true;
 }
 
 
 }
 
 
@@ -750,14 +866,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 != ')') {
@@ -773,16 +893,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)
-               panic("Invalid method descriptor: too many arguments");
+       if (argcount > 255) {
+               *exceptionptr =
+                       new_classformaterror(c, "Too many arguments in signature");
+
+               return 0;
+       }
 
        return argcount;
 
 
        return argcount;
 
@@ -869,59 +997,79 @@ 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 attrnum, i;
        u4 jtype;
        u4 jtype;
-       u4 pindex = field_load_NOVALUE;                               /* constantvalue_index */
+       u4 pindex = field_load_NOVALUE;     /* constantvalue_index */
+       utf *u;
+
+       if (!check_classbuffer_size(cb, 2 + 2 + 2))
+               return false;
+
+       f->flags = suck_u2(cb);
+
+       if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+               return false;
+       f->name = u;
+
+       if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+               return false;
+       f->descriptor = u;
 
 
-       f->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 */
-       
        if (opt_verify) {
                /* check name */
                if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
                        panic("Field with invalid name");
                
                /* check flag consistency */
        if (opt_verify) {
                /* check name */
                if (!is_valid_name_utf(f->name) || f->name->text[0] == '<')
                        panic("Field with invalid name");
                
                /* 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 ((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 ((f->flags & ACC_TRANSIENT) != 0)
-                               panic("Interface field declared transient");
+               i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
+
+               if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
+                       ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
+                       *exceptionptr =
+                               new_classformaterror(c,
+                                                                        "Illegal field modifiers: 0x%X",
+                                                                        f->flags);
+                       return false;
+               }
+
+               if (c->flags & ACC_INTERFACE) {
+                       if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
+                               != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
+                               f->flags & ACC_TRANSIENT) {
+                               *exceptionptr =
+                                       new_classformaterror(c,
+                                                                                "Illegal field modifiers: 0x%X",
+                                                                                f->flags);
+                               return false;
+                       }
                }
 
                /* check descriptor */
                }
 
                /* 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;
@@ -931,77 +1079,109 @@ 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++) {
        for (i = 0; i < attrnum; i++) {
-               utf *aname;
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
 
 
-               aname = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
-               
-               if (aname != utf_constantvalue) {
-                       /* unknown attribute */
-                       skipattributebody();
+               if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                       return false;
 
 
-               } else {
-                       /* constant value attribute */
+               if (u == utf_ConstantValue) {
+                       if (!check_classbuffer_size(cb, 4 + 2))
+                               return false;
 
 
-                       if (pindex != field_load_NOVALUE)
-                               panic("Field has more than one ConstantValue attribute");
-                       
                        /* check attribute length */
                        /* check attribute length */
-                       if (suck_u4() != 2)
-                               panic("ConstantValue attribute has invalid length");
+                       if (suck_u4(cb) != 2) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Wrong size for VALUE attribute");
+                               return false;
+                       }
+                       
+                       /* constant value attribute */
+                       if (pindex != field_load_NOVALUE) {
+                               *exceptionptr =
+                                       new_classformaterror(c,
+                                                                                "Multiple ConstantValue attributes");
+                               return false;
+                       }
                        
                        /* index of value in constantpool */            
                        
                        /* index of value in constantpool */            
-                       pindex = suck_u2();
+                       pindex = suck_u2(cb);
                
                        /* initialize field with value from constantpool */             
                        switch (jtype) {
                        case TYPE_INT: {
                
                        /* initialize field with value from constantpool */             
                        switch (jtype) {
                        case TYPE_INT: {
-                               constant_integer *ci = 
-                                       class_getconstant(c, pindex, CONSTANT_Integer);
+                               constant_integer *ci; 
+
+                               if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
+                                       return false;
+
                                f->value.i = ci->value;
                        }
                        break;
                                        
                        case TYPE_LONG: {
                                f->value.i = ci->value;
                        }
                        break;
                                        
                        case TYPE_LONG: {
-                               constant_long *cl = 
-                                       class_getconstant(c, pindex, CONSTANT_Long);
+                               constant_long *cl; 
+
+                               if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
+                                       return false;
+
                                f->value.l = cl->value;
                        }
                        break;
 
                        case TYPE_FLOAT: {
                                f->value.l = cl->value;
                        }
                        break;
 
                        case TYPE_FLOAT: {
-                               constant_float *cf = 
-                                       class_getconstant(c, pindex, CONSTANT_Float);
+                               constant_float *cf;
+
+                               if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
+                                       return false;
+
                                f->value.f = cf->value;
                        }
                        break;
                                                                                        
                        case TYPE_DOUBLE: {
                                f->value.f = cf->value;
                        }
                        break;
                                                                                        
                        case TYPE_DOUBLE: {
-                               constant_double *cd = 
-                                       class_getconstant(c, pindex, CONSTANT_Double);
+                               constant_double *cd;
+
+                               if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
+                                       return false;
+
                                f->value.d = cd->value;
                        }
                        break;
                                                
                                f->value.d = cd->value;
                        }
                        break;
                                                
-                       case TYPE_ADDRESS: { 
-                               utf *u = class_getconstant(c, pindex, CONSTANT_String);
-                               /* create javastring from compressed utf8-string */                                     
+                       case TYPE_ADDRESS:
+                               if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
+                                       return false;
+
+                               /* create javastring from compressed utf8-string */
                                f->value.a = literalstring_new(u);
                                f->value.a = literalstring_new(u);
-                       }
-                       break;
+                               break;
        
                        default: 
        
                        default: 
-                               log_text ("Invalid Constant - Type");
+                               log_text("Invalid Constant - Type");
                        }
                        }
+
+               } else {
+                       /* unknown attribute */
+                       if (!skipattributebody(cb))
+                               return false;
                }
        }
                }
        }
-}
 
 
+       /* everything was ok */
+
+       return true;
+}
 
 
-/********************** function: field_free **********************************/
 
 
-static void field_free (fieldinfo *f)
+/********************** function: field_free **********************************/
+
+static void field_free(fieldinfo *f)
 {
        /* empty */
 }
 {
        /* empty */
 }
@@ -1022,80 +1202,129 @@ 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;
+       utf *u;
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       initObjectLock(&m->header);
+#endif
+
 #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);
+
+       if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+               return false;
+       m->name = u;
+
+       if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+               return false;
+       m->descriptor = u;
 
        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) {
                argcount++; /* count the 'this' argument */
 
        if (opt_verify) {
-               if (argcount > 255)
-                       panic("Method has more than 255 arguments");
+               if (argcount > 255) {
+                       *exceptionptr =
+                               new_classformaterror(c, "Too many arguments in signature");
+                       return false;
+               }
 
                /* 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 ((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 (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
+                               *exceptionptr =
+                                       new_classformaterror(c,
+                                                                                "Illegal method modifiers: 0x%X",
+                                                                                m->flags);
+                               return false;
+                       }
+
+                       if (m->flags & ACC_ABSTRACT) {
+                               if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
+                                                                ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Illegal method modifiers: 0x%X",
+                                                                                        m->flags);
+                                       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) {
+                               if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Illegal method modifiers: 0x%X",
+                                                                                        m->flags);
+                                       return false;
+                               }
                        }
                        }
+
                        if (m->name == utf_init) {
                        if (m->name == utf_init) {
-                               if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
-                                                                | ACC_NATIVE | ACC_ABSTRACT)) != 0)
+                               if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
+                                                               ACC_NATIVE | ACC_ABSTRACT))
                                        panic("Instance initialization method has invalid flags set");
                        }
                }
        }
                
        m->jcode = NULL;
                                        panic("Instance initialization method has invalid flags set");
                        }
                }
        }
                
        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->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;
@@ -1107,108 +1336,209 @@ static void method_load(methodinfo *m, classinfo *c)
                m->stubroutine = createcompilerstub(m);
 
        } else {
                m->stubroutine = createcompilerstub(m);
 
        } else {
+               /*if (useinlining) {
+                       log_text("creating native stub:");
+                       method_display(m);
+               }*/
                functionptr f = native_findfunction(c->name, m->name, m->descriptor, 
                functionptr f = native_findfunction(c->name, m->name, m->descriptor, 
-                                                                                       (m->flags & ACC_STATIC) != 0);
-               if (f) {
+                                                       (m->flags & ACC_STATIC) != 0);
+#ifdef STATIC_CLASSPATH
+               if (f) 
+#endif
+                {
                        m->stubroutine = createnativestub(f, m);
                }
        }
        
                        m->stubroutine = createnativestub(f, m);
                }
        }
        
+       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 (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);
-                               }
+               if (!check_classbuffer_size(cb, 2))
+                       return false;
+
+               if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                       return false;
+
+               if (aname == utf_Code) {
+                       if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Code attribute in native or abstract methods");
+
+                                       return false;
                        }
                        }
-                       else
-                       skipattributebody();
+                       
+                       if (m->jcode) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple Code attributes");
 
 
-               } else {
-                       u4 codelen;
-                       if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
-                               panic("Code attribute for native or abstract method");
+                               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);
+                                       if (!(m->exceptiontable[j].catchtype =
+                                                 class_getconstant(c, idx, CONSTANT_Class)))
+                                               return false;
                                }
                                }
-                       }                       
-                       {
-                               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;
+
+                               if (!(caname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                                       return false;
+
+                               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;
+                               }
                        }
                        }
+
+               } else if (aname == utf_Exceptions) {
+                       s4 j;
+
+                       if (m->thrownexceptions) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple Exceptions attributes");
+                               return false;
+                       }
+
+                       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++) {
+                               if (!((m->thrownexceptions)[j] =
+                                         class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+                                       return false;
+                       }
+                               
+               } 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;
 }
 
 
 }
 
 
@@ -1253,6 +1583,24 @@ void method_display(methodinfo *m)
        printf("\n");
 }
 
        printf("\n");
 }
 
+/************** Function: method_display_w_class  (debugging only) **************/
+
+void method_display_w_class(methodinfo *m)
+{
+        printflags(m->class->flags);
+        printf(" "); fflush(stdout);
+        utf_display(m->class->name);
+        printf(".");fflush(stdout);
+
+        printf("   ");
+        printflags(m->flags);
+        printf(" "); fflush(stdout);
+        utf_display(m->name);
+        printf(" "); fflush(stdout);
+        utf_display(m->descriptor);
+        printf("\n"); fflush(stdout);
+}
+
 /************** Function: method_display_flags_last  (debugging only) **************/
 
 void method_display_flags_last(methodinfo *m)
 /************** Function: method_display_flags_last  (debugging only) **************/
 
 void method_display_flags_last(methodinfo *m)
@@ -1272,7 +1620,7 @@ 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)
 {
@@ -1283,54 +1631,6 @@ static bool method_canoverwrite(methodinfo *m, methodinfo *old)
 }
 
 
 }
 
 
-
-
-/******************************************************************************/
-/************************ Functions for class *********************************/
-/******************************************************************************/
-
-
-/******************** function:: class_getconstant ******************************
-
-       retrieves the value at position 'pos' of the constantpool of a class
-       if the type of the value is other than 'ctype' the system is stopped
-
-*******************************************************************************/
-
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
-       /* invalid position in constantpool */
-       /* (pos == 0 is caught by type comparison) */
-       if (pos >= c->cpcount)
-               panic("Attempt to access constant outside range");
-
-       /* check type of constantpool entry */
-
-       if (c->cptags[pos] != ctype) {
-               class_showconstantpool(c);
-               error("Type mismatch on constant: %d requested, %d here (class_getconstant)",
-                         (int) ctype, (int) c->cptags[pos]);
-       }
-               
-       return c->cpinfos[pos];
-}
-
-
-/********************* Function: class_constanttype ****************************
-
-       Determines the type of a class entry in the ConstantPool
-       
-*******************************************************************************/
-
-u4 class_constanttype(classinfo *c, u4 pos)
-{
-       if (pos >= c->cpcount)
-               panic("Attempt to access constant outside range");
-
-       return c->cptags[pos];
-}
-
-
 /******************** function: class_loadcpool ********************************
 
        loads the constantpool of a class, 
 /******************** function: class_loadcpool ********************************
 
        loads the constantpool of a class, 
@@ -1340,7 +1640,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 
@@ -1348,17 +1648,17 @@ static void class_loadcpool(classinfo *c)
           been traversed the references can be resolved. 
           (only in specific order)                                                */
        
           been traversed the references can be resolved. 
           (only in specific order)                                                */
        
-       /* CONSTANT_Class_info entries */
-       typedef struct forward_class {      
-               struct forward_class *next; 
-               u2 thisindex;               
-               u2 name_index;              
-       } forward_class;                    
-                                        
-       /* CONSTANT_String */                                      
-       typedef struct forward_string { 
-               struct forward_string *next; 
-               u2 thisindex;                
+       /* CONSTANT_Class entries */
+       typedef struct forward_class {
+               struct forward_class *next;
+               u2 thisindex;
+               u2 name_index;
+       } forward_class;
+
+       /* CONSTANT_String */
+       typedef struct forward_string {
+               struct forward_string *next;
+               u2 thisindex;
                u2 string_index;
        } forward_string;
 
                u2 string_index;
        } forward_string;
 
@@ -1371,7 +1671,7 @@ static void class_loadcpool(classinfo *c)
        } forward_nameandtype;
 
        /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
        } forward_nameandtype;
 
        /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
-       typedef struct forward_fieldmethint {   
+       typedef struct forward_fieldmethint {
                struct forward_fieldmethint *next;
                u2 thisindex;
                u1 tag;
                struct forward_fieldmethint *next;
                u2 thisindex;
                u1 tag;
@@ -1381,25 +1681,39 @@ static void class_loadcpool(classinfo *c)
 
 
        u4 idx;
 
 
        u4 idx;
-       long int dumpsize = dump_size ();
 
        forward_class *forward_classes = NULL;
        forward_string *forward_strings = NULL;
        forward_nameandtype *forward_nameandtypes = NULL;
        forward_fieldmethint *forward_fieldmethints = NULL;
 
 
        forward_class *forward_classes = NULL;
        forward_string *forward_strings = NULL;
        forward_nameandtype *forward_nameandtypes = NULL;
        forward_fieldmethint *forward_fieldmethints = NULL;
 
+       forward_class *nfc;
+       forward_string *nfs;
+       forward_nameandtype *nfn;
+       forward_fieldmethint *nff;
+
+       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 < 1) {
+               *exceptionptr = new_classformaterror(c, "Illegal constant pool size");
+               return false;
+       }
        
        
-#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 */
@@ -1415,277 +1729,345 @@ static void class_loadcpool(classinfo *c)
                   
        idx = 1;
        while (idx < cpcount) {
                   
        idx = 1;
        while (idx < cpcount) {
+               u4 t;
+
                /* get constant type */
                /* get constant type */
-               u4 t = suck_u1();
+               if (!check_classbuffer_size(cb, 1))
+                       return false;
+
+               t = suck_u1(cb);
 
                switch (t) {
 
                switch (t) {
-                       case CONSTANT_Class: { 
-                               forward_class *nfc = DNEW(forward_class);
+               case CONSTANT_Class:
+                       nfc = NEW(forward_class);
 
 
-                               nfc -> next = forward_classes;                                                                                  
-                               forward_classes = nfc;
+                       nfc->next = forward_classes;
+                       forward_classes = nfc;
 
 
-                               nfc -> thisindex = idx;
-                               /* reference to CONSTANT_NameAndType */
-                               nfc -> name_index = suck_u2 (); 
+                       nfc->thisindex = idx;
+                       /* reference to CONSTANT_NameAndType */
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
 
 
-                               idx++;
-                               break;
-                               }
+                       nfc->name_index = suck_u2(cb);
+
+                       idx++;
+                       break;
                        
                        
-                       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;
-                               }
-                               
-                       case CONSTANT_String: {
-                               forward_string *nfs = DNEW(forward_string);
+               case CONSTANT_String:
+                       nfs = NEW(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:
+                       nfn = NEW(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_Fieldref:
+               case CONSTANT_Methodref:
+               case CONSTANT_InterfaceMethodref:
+                       nff = NEW(forward_fieldmethint);
+                       
+                       nff->next = forward_fieldmethints;
+                       forward_fieldmethints = nff;
 
 
-#ifdef STATISTICS
-       count_const_pool_len += sizeof(constant_integer);
-#endif
+                       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);
 
 
-                               ci -> value = suck_s4 ();
-                               cptags [idx] = CONSTANT_Integer;
-                               cpinfos [idx] = ci;
-                               idx ++;
+                       /* name and descriptor of the field or method */
+                       nff->nameandtype_index = suck_u2(cb);
+
+                       idx++;
+                       break;
                                
                                
-                               break;
-                               }
+               case CONSTANT_Integer: {
+                       constant_integer *ci = NEW(constant_integer);
+
+#if defined(STATISTICS)
+                       if (opt_stat)
+                               count_const_pool_len += sizeof(constant_integer);
+#endif
+
+                       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) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Invalid constant pool entry");
+                               return false;
+                       }
+                       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) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Invalid constant pool entry");
+                               return false;
+                       }
+                       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((char *) (cb->pos + 1),
+                                                         (char *) (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((char *) (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:
+                       *exceptionptr =
+                               new_classformaterror(c, "Illegal constant pool type");
+                       return false;
+               }  /* 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, because we cannot link the class currently
+                          loading */
+                       list_addfirst(&unlinkedclasses, tc);
+
+                       cpinfos[forward_classes->thisindex] = tc;
+
+               } else {
+                       cpinfos[forward_classes->thisindex] = class_new(name);
                }
 
                }
 
+               nfc = forward_classes;
+               forward_classes = forward_classes->next;
+               FREE(nfc, forward_class);
+       }
+
        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------------------"); */
-               /* resolve utf-string */                
-               cptags   [forward_strings -> thisindex] = CONSTANT_String;
-               cpinfos  [forward_strings -> thisindex] = text;
+               utf *text =
+                       class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+
+               /* resolve utf-string */
+               cptags[forward_strings->thisindex] = CONSTANT_String;
+               cpinfos[forward_strings->thisindex] = text;
                
                
-               forward_strings = forward_strings -> next;
-               }       
+               nfs = forward_strings;
+               forward_strings = forward_strings->next;
+               FREE(nfs, forward_string);
+       }
 
        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 */
-                       if (!is_valid_name_utf(cn->name))
-                               panic("NameAndType with invalid name");
+                       if (!is_valid_name_utf(cn->name)) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
+
                        /* disallow referencing <clinit> among others */
                        /* disallow referencing <clinit> among others */
-                       if (cn->name->text[0] == '<' && cn->name != utf_init)
-                               panic("NameAndType with invalid special name");
+                       if (cn->name->text[0] == '<' && cn->name != utf_init) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
                }
 
                }
 
-               cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
-               cpinfos  [forward_nameandtypes -> thisindex] = cn;
-               
-               forward_nameandtypes = forward_nameandtypes -> next;
-               }
+               cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
+               cpinfos[forward_nameandtypes->thisindex] = cn;
 
 
+               nfn = forward_nameandtypes;
+               forward_nameandtypes = forward_nameandtypes->next;
+               FREE(nfn, forward_nameandtype);
+       }
 
 
-       while (forward_fieldmethints)  {
+       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;
-               }               
-       
-               forward_fieldmethints = forward_fieldmethints -> next;
-
+                       checkmethoddescriptor(c, fmi->descriptor);
+                       break;
                }
                }
+       
+               nff = forward_fieldmethints;
+               forward_fieldmethints = forward_fieldmethints->next;
+               FREE(nff, forward_fieldmethint);
+       }
 
 
-/*     class_showconstantpool(c); */
+       /* everything was ok */
 
 
-       dump_release(dumpsize);
+       return true;
 }
 
 
 }
 
 
@@ -1702,45 +2084,141 @@ static void class_loadcpool(classinfo *c)
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static int class_load(classinfo *c)
+classinfo *class_load_intern(classbuffer *cb);
+
+classinfo *class_load(classinfo *c)
 {
 {
-       u4 i;
-       u4 mi,ma;
+       classbuffer *cb;
+       classinfo *r;
 
 
-#ifdef STATISTICS
-       count_class_loads++;
+#if defined(USE_THREADS)
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
 #endif
 
 #endif
 
-       /* output for debugging purposes */
-       if (loadverbose) {              
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Loading class: ");
-               utf_sprint(logtext + strlen(logtext), c->name);
-               log_text(logtext);
+       /* maybe the class is already loaded */
+       if (c->loaded) {
+#if defined(USE_THREADS)
+               builtin_monitorexit((java_objectheader *) c);
+#endif
+
+               return c;
        }
        }
-       
+
+       /* measure time */
+
+       if (getcompilingtime)
+               compilingtime_stop();
+
+       if (getloadingtime)
+               loadingtime_start();
+
        /* load classdata, throw exception on error */
 
        /* load classdata, throw exception on error */
 
-       if (!suck_start(c->name)) {
-               *exceptionptr = new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
-                                                                                                c->name);
-               return false;
+       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);
+
+#if defined(USE_THREADS)
+               builtin_monitorexit((java_objectheader *) c);
+#endif
+
+               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)
+               loadingtime_stop();
+
+       if (getcompilingtime)
+               compilingtime_start();
+
+#if defined(USE_THREADS)
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+#endif
+
+       return r;
+}
+
+
+classinfo *class_load_intern(classbuffer *cb)
+{
+       classinfo *c;
+       classinfo *tc;
+       u4 i;
+       u4 ma, mi;
+       char msg[MAXLOGTEXT];               /* maybe we get an exception */
+
+       /* 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 */
+       if (loadverbose)
+               log_message_class("Loading class: ", c);
+       
+       /* class is somewhat loaded */
+       c->loaded = true;
+
+       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+               return NULL;
+
        /* check signature */
        /* check signature */
-       if (suck_u4() != MAGIC)
-               panic("Can not find class-file signature");
+       if (suck_u4(cb) != MAGIC) {
+               *exceptionptr = new_classformaterror(c, "Bad magic number");
+
+               return NULL;
+       }
 
        /* check version */
 
        /* check version */
-       mi = suck_u2();
-       ma = suck_u2();
-#if 0
-       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_unsupportedclassversionerror(c,
+                                                                                        "Unsupported major.minor version %d.%d",
+                                                                                        ma, mi);
+
+               return NULL;
        }
        }
-#endif
 
 
-       class_loadcpool(c);
+       /* load the constant pool */
+       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;     
@@ -1749,86 +2227,134 @@ 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) {
-/*             char message[MAXLOGTEXT]; */
-/*             utf_sprint(message, c->name); */
-/*             sprintf(message + strlen(message), " (wrong name: "); */
-/*             utf_sprint(message + strlen(message), class_getconstant(c, i, CONSTANT_Class)); */
-/*             sprintf(message + strlen(message), ")"); */
-
-/*             *exceptionptr = new_exception_message("java/lang/NoClassDefFoundError", */
-/*                                                                                       message); */
-/*             return false; */
-               panic("Invalid this_class in class file");
+       i = suck_u2(cb);
+       if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
+               return NULL;
+
+       if (tc != c) {
+               utf_sprint(msg, c->name);
+               sprintf(msg + strlen(msg), " (wrong name: ");
+               utf_sprint(msg + strlen(msg), tc->name);
+               sprintf(msg + strlen(msg), ")");
+
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoClassDefFoundError, msg);
+
+               return NULL;
        }
        
        /* retrieve superclass */
        }
        
        /* retrieve superclass */
-       if ((i = suck_u2())) {
-               c->super = class_getconstant(c, i, CONSTANT_Class);
+       if ((i = suck_u2(cb))) {
+               if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
+                       return NULL;
 
                /* java.lang.Object may not have a super 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);
+               if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+                       return NULL;
        }
 
        /* 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
@@ -1863,84 +2389,109 @@ static int class_load(classinfo *c)
 
                /* Check fields */
                memset(hashtab, 0, sizeof(u2) * (hashlen + len));
 
                /* Check fields */
                memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
                for (i = 0; i < c->fieldscount; ++i) {
                        fieldinfo *fi = c->fields + i;
                for (i = 0; i < c->fieldscount; ++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));
+               memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
+
                for (i = 0; i < c->methodscount; ++i) {
                        methodinfo *mi = c->methods + i;
                for (i = 0; i < c->methodscount; ++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;
+
+                       /*{ JOWENN
+                               int dbg;
+                               for (dbg=0;dbg<hashlen+hashlen/5;++dbg){
+                                       printf("Hash[%d]:%d\n",dbg,hashtab[dbg]);
+                               }
+                       }*/
+
+                       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
 
 #endif
 
-       /* load variable-length attribute structures */ 
-       attribute_load(suck_u2(), c);
+       /* load attribute structures */
+       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
+       /* Pre java 1.5 version don't check this. This implementation is like
+          java 1.5 do it: for class file version 45.3 we don't check it, older
+          versions are checked.
+        */
+       if ((ma == 45 && mi > 3) || ma > 45) {
+               /* check if all data has been read */
+               s4 classdata_left = ((cb->data + cb->size) - cb->pos - 1);
+
+               if (classdata_left > 0) {
+                       *exceptionptr =
+                               new_classformaterror(c, "Extra bytes at the end of class file");
+                       return NULL;
+               }
+       }
+#endif
 
 
-       c->loaded = true;
+       if (loadverbose)
+               log_message_class("Loading done class: ", c);
 
 
-       return true;
+       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.
@@ -1952,13 +2503,8 @@ static s4 class_highestinterface(classinfo *c)
        s4 h;
        s4 i;
        
        s4 h;
        s4 i;
        
-       if (!(c->flags & ACC_INTERFACE)) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Interface-methods count requested for non-interface:  ");
-       utf_sprint(logtext + strlen(logtext), c->name);
-       error("%s",logtext);
-       }
-    
+    /* check for ACC_INTERFACE bit already done in class_link_intern */
+
     h = c->index;
        for (i = 0; i < c->interfacescount; i++) {
                s4 h2 = class_highestinterface(c->interfaces[i]);
     h = c->index;
        for (i = 0; i < c->interfacescount; i++) {
                s4 h2 = class_highestinterface(c->interfaces[i]);
@@ -1971,52 +2517,54 @@ static s4 class_highestinterface(classinfo *c)
 
 /* class_addinterface **********************************************************
 
 
 /* class_addinterface **********************************************************
 
-       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     j, m;
-       s4     i     = ic->index;
-       vftbl *vftbl = c->vftbl;
-       
-       if (i >= vftbl->interfacetablelength)
+       s4     i   = ic->index;
+       vftbl_t *v = c->vftbl;
+
+       if (i >= v->interfacetablelength)
                panic ("Inernal error: interfacetable overflow");
                panic ("Inernal error: interfacetable overflow");
-       if (vftbl->interfacetable[-i])
+
+       if (v->interfacetable[-i])
                return;
 
        if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
                return;
 
        if (ic->methodscount == 0) {  /* fake entry needed for subtype test */
-               vftbl->interfacevftbllength[i] = 1;
-               vftbl->interfacetable[-i] = MNEW(methodptr, 1);
-               vftbl->interfacetable[-i][0] = NULL;
-               }
-       else {
-               vftbl->interfacevftbllength[i] = ic->methodscount;
-               vftbl->interfacetable[-i] = MNEW(methodptr, ic->methodscount); 
+               v->interfacevftbllength[i] = 1;
+               v->interfacetable[-i] = MNEW(methodptr, 1);
+               v->interfacetable[-i][0] = NULL;
 
 
-#ifdef STATISTICS
-       count_vftbl_len += sizeof(methodptr) *
-                                (ic->methodscount + (ic->methodscount == 0));
+       } else {
+               v->interfacevftbllength[i] = ic->methodscount;
+               v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
+
+#if defined(STATISTICS)
+               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];
+                                               v->interfacetable[-i][j] = v->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]);
@@ -2035,11 +2583,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] != '[')
@@ -2047,17 +2590,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 */
@@ -2065,12 +2625,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));
@@ -2083,17 +2659,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;
 }
 
 
 }
 
 
@@ -2110,28 +2677,36 @@ 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_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_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)
+                       if (!class_load(comp))
+                               return NULL;
+
+               if (!class_link(comp))
+                       return NULL;
+       }
 
        /* Allocate the arraydescriptor */
        desc = NEW(arraydescriptor);
 
        /* Allocate the arraydescriptor */
        desc = NEW(arraydescriptor);
@@ -2140,7 +2715,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)
@@ -2153,8 +2728,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;
@@ -2163,42 +2738,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;
@@ -2219,54 +2802,126 @@ 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;
+
+#if defined(USE_THREADS)
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
+#endif
+
+       /* maybe the class is already linked */
+       if (c->linked) {
+#if defined(USE_THREADS)
+               builtin_monitorexit((java_objectheader *) c);
+#endif
+
+               return c;
+       }
 
 
-void class_link(classinfo *c)
+       /* measure time */
+
+       if (getcompilingtime)
+               compilingtime_stop();
+
+       if (getloadingtime)
+               loadingtime_start();
+
+       /* 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)
+               loadingtime_stop();
+
+       if (getcompilingtime)
+               compilingtime_start();
+
+#if defined(USE_THREADS)
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+#endif
+
+       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                   */
 {
        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                   */
+       classinfo *super;             /* super class                              */
+       classinfo *tc;                /* temporary class variable                 */
+       vftbl_t *v;                   /* vftbl of current class                   */
        s4 i;                         /* interface/method/field counter           */
        s4 i;                         /* interface/method/field counter           */
-       arraydescriptor *arraydesc = NULL;  /* descriptor for array classes       */
+       arraydescriptor *arraydesc;   /* descriptor for array classes             */
+
+       /* maybe the class is already linked */
+       if (c->linked)
+               return c;
 
 
+       /* maybe the class is not loaded */
+       if (!c->loaded)
+               if (!class_load(c))
+                       return NULL;
 
 
-       /*  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);
+
+       /* ok, this class is somewhat linked */
+       c->linked = true;
 
 
-       /*  check interfaces */
+       arraydesc = NULL;
+
+       /* check interfaces */
 
        for (i = 0; i < c->interfacescount; i++) {
 
        for (i = 0; i < c->interfacescount; i++) {
-               ic = c->interfaces[i];
-               if (!ic->linked) {
-                       list_remove(&unlinkedclasses, c);
-                       list_addlast(&unlinkedclasses, c);
-                       return; 
+               tc = c->interfaces[i];
+
+               /* detect circularity */
+               if (tc == c) {
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_ClassCircularityError,
+                                                                                c->name);
+                       return NULL;
                }
                }
-               if ((ic->flags & ACC_INTERFACE) == 0) {
-                       dolog("Specified interface is not declared as interface:");
-                       log_utf(ic->name);
-                       dolog("in");
-                       log_utf(c->name);
-                       panic("Specified interface is not declared as interface");
+
+               if (!tc->loaded)
+                       if (!class_load(tc))
+                               return NULL;
+
+               if (!(tc->flags & ACC_INTERFACE)) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_IncompatibleClassChangeError,
+                                                                         "Implementing class");
+                       return NULL;
                }
                }
+
+               if (!tc->linked)
+                       if (!class_link(tc))
+                               return NULL;
        }
        
        }
        
-       /*  check super class */
+       /* check super class */
+
+       super = c->super;
 
        if (super == NULL) {          /* class java.lang.Object */
                c->index = 0;
 
        if (super == NULL) {          /* class java.lang.Object */
                c->index = 0;
@@ -2279,28 +2934,40 @@ 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)
+               if (!super->loaded)
+                       if (!class_load(super))
+                               return NULL;
+
+               if (super->flags & ACC_INTERFACE) {
+                       /* java.lang.IncompatibleClassChangeError: class a has interface java.lang.Cloneable as super class */
                        panic("Interface specified as super class");
                        panic("Interface specified as super class");
+               }
+
+               /* Don't allow extending final classes */
+               if (super->flags & ACC_FINAL) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_VerifyError,
+                                                                         "Cannot inherit from final class");
+                       return NULL;
+               }
+               
+               if (!super->linked)
+                       if (!class_link(super))
+                               return NULL;
 
                /* handle array classes */
 
                /* 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) {
-                               list_remove(&unlinkedclasses, c);
-                               list_addlast(&unlinkedclasses, c);
-                               return; 
-                       }
+                       if (!(arraydesc = class_link_array(c)))
+                               return NULL;
 
 
-               /* Don't allow extending final classes */
-               if (super->flags & ACC_FINAL)
-                       panic("Trying to extend final class");
-               
                if (c->flags & ACC_INTERFACE)
                        c->index = interfaceindex++;
                else
                if (c->flags & ACC_INTERFACE)
                        c->index = interfaceindex++;
                else
@@ -2313,69 +2980,65 @@ 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++) {
                methodinfo *m = &(c->methods[i]);
                        
                if (!(m->flags & ACC_STATIC)) { /* is instance method */
        /* compute vftbl length */
 
        for (i = 0; i < c->methodscount; i++) {
                methodinfo *m = &(c->methods[i]);
                        
                if (!(m->flags & ACC_STATIC)) { /* is instance method */
-                       classinfo *sc = super;
-                       while (sc) {
-                               int j;
-                               for (j = 0; j < sc->methodscount; j++) {
-                                       if (method_canoverwrite(m, &(sc->methods[j]))) {
-                                               if ((sc->methods[j].flags & ACC_PRIVATE) != 0)
+                       tc = super;
+
+                       while (tc) {
+                               s4 j;
+                               for (j = 0; j < tc->methodscount; j++) {
+                                       if (method_canoverwrite(m, &(tc->methods[j]))) {
+                                               if (tc->methods[j].flags & ACC_PRIVATE)
                                                        goto notfoundvftblindex;
                                                        goto notfoundvftblindex;
-                                               if ((sc->methods[j].flags & ACC_FINAL) != 0) {
-                                                       log_utf(c->name);
-                                                       log_utf(sc->name);
-                                                       log_utf(sc->methods[j].name);
-                                                       log_utf(sc->methods[j].descriptor);
-                                                       panic("Trying to overwrite final method");
+
+                                               if (tc->methods[j].flags & ACC_FINAL) {
+                                                       /* class a overrides final method . */
+                                                       *exceptionptr =
+                                                               new_exception(string_java_lang_VerifyError);
+                                                       return NULL;
                                                }
                                                }
-                                               m->vftblindex = sc->methods[j].vftblindex;
+                                               m->vftblindex = tc->methods[j].vftblindex;
                                                goto foundvftblindex;
                                        }
                                }
                                                goto foundvftblindex;
                                        }
                                }
-                               sc = sc->super;
+                               tc = tc->super;
                        }
                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 */
 
        interfacetablelength = 0;
 #endif
 
        /* compute interfacetable length */
 
        interfacetablelength = 0;
-       c2 = c;
-       while (c2) {
-               for (i = 0; i < c2->interfacescount; i++) {
-                       s4 h = class_highestinterface (c2->interfaces[i]) + 1;
+       tc = c;
+       while (tc) {
+               for (i = 0; i < tc->interfacescount; i++) {
+                       s4 h = class_highestinterface(tc->interfaces[i]) + 1;
                        if (h > interfacetablelength)
                                interfacetablelength = h;
                }
                        if (h > interfacetablelength)
                                interfacetablelength = h;
                }
-               c2 = c2->super;
+               tc = tc->super;
        }
 
        /* 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;
        v->class = c;
                                  (interfacetablelength > 1));
        c->header.vftbl = c->vftbl = v;
        v->class = c;
@@ -2407,7 +3070,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;
@@ -2419,8 +3082,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++) {
@@ -2430,37 +3094,32 @@ void class_link(classinfo *c)
        
        /* add interfaces */
        
        
        /* add interfaces */
        
-       for (c2 = c; c2 != NULL; c2 = c2->super)
-               for (i = 0; i < c2->interfacescount; i++) {
-                       class_addinterface(c, c2->interfaces[i]);
-               }
+       for (tc = c; tc != NULL; tc = tc->super)
+               for (i = 0; i < tc->interfacescount; i++)
+                       class_addinterface(c, tc->interfaces[i]);
 
        /* add finalizer method (not for java.lang.Object) */
 
 
        /* add finalizer method (not for java.lang.Object) */
 
-       if (super != NULL) {
+       if (super) {
                methodinfo *fi;
                methodinfo *fi;
-               static utf *finame = NULL;
-               static utf *fidesc = NULL;
 
 
-               if (finame == NULL)
-                       finame = utf_finalize;
-               if (fidesc == NULL)
-                       fidesc = utf_fidesc;
+               fi = class_findmethod(c, utf_finalize, utf_void__void);
 
 
-               fi = class_findmethod(c, finame, fidesc);
-               if (fi != NULL) {
-                       if (!(fi->flags & ACC_STATIC)) {
+               if (fi)
+                       if (!(fi->flags & ACC_STATIC))
                                c->finalizer = fi;
                                c->finalizer = fi;
-                       }
-               }
        }
 
        /* 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;
 }
 
 
 }
 
 
@@ -2470,44 +3129,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;
+                               }
                        }
                }
                        }
                }
+       }
+
+       if (c->cptags)
+               MFREE(c->cptags, u1, c->cpcount);
 
 
-       MFREE (c -> cptags,  u1, c -> cpcount);
-       MFREE (c -> cpinfos, voidptr, c -> cpcount);
+       if (c->cpinfos)
+               MFREE(c->cpinfos, voidptr, c->cpcount);
 }
 
 
 }
 
 
@@ -2517,21 +3181,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)
@@ -2542,21 +3212,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); */
 }
 
 
 }
 
 
@@ -2570,7 +3240,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]);                                                         
@@ -2592,28 +3262,28 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-static
-fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
        fieldinfo *fi;
 
        /* search for field in class c */
        for (i = 0; i < c->fieldscount; i++) { 
 {
        s4 i;
        fieldinfo *fi;
 
        /* 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]);                                                         
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+                       return &(c->fields[i]);
+               }
     }
 
        /* try superinterfaces recursively */
     }
 
        /* try superinterfaces recursively */
-       for (i=0; i<c->interfacescount; ++i) {
-               fi = class_resolvefield_int(c->interfaces[i],name,desc);
+       for (i = 0; i < c->interfacescount; ++i) {
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
                if (fi)
                        return fi;
        }
 
        /* try superclass */
        if (c->super)
                if (fi)
                        return fi;
        }
 
        /* try superclass */
        if (c->super)
-               return class_resolvefield_int(c->super,name,desc);
+               return class_resolvefield_int(c->super, name, desc);
 
        /* not found */
        return NULL;
 
        /* not found */
        return NULL;
@@ -2637,11 +3307,14 @@ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
-       fi = class_resolvefield_int(c,name,desc);
+       fi = class_resolvefield_int(c, name, desc);
 
        if (!fi) {
                if (except)
 
        if (!fi) {
                if (except)
-                       *exceptionptr = new_exception("java/lang/NoSuchFieldError");
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
+                                                                                name);
+
                return NULL;
        }
 
                return NULL;
        }
 
@@ -2662,60 +3335,20 @@ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
 s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
-       //#define JOWENN_DEBUG1
-       //#define JOWENN_DEBUG2
-#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))) {
                        return i;
                }
        }
 
                if ((c->methods[i].name == name) && ((desc == NULL) ||
                                                                                         (c->methods[i].descriptor == desc))) {
                        return i;
                }
        }
 
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
-
        return -1;
 }
 
        return -1;
 }
 
@@ -2730,62 +3363,10 @@ s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
 
 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 {
 
 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 {
-#if 0
-       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++) {
-#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);       
-
-               MFREE(buffer, char, buffer_len);
-#endif 
-               
-               if ((c->methods[i].name == name) && ((desc == NULL) ||
-                                                                                        (c->methods[i].descriptor == desc))) {
-                       return &(c->methods[i]);
-               }
-       }
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
-       return NULL;
-#endif
+       s4 idx = class_findmethodIndex(c, name, desc);
 
 
-       s4 idx=class_findmethodIndex(c, name, desc);
-/*     if (idx==-1) log_text("class_findmethod: method not found");*/
-       if (idx == -1) return NULL;
+       if (idx == -1)
+               return NULL;
 
        return &(c->methods[idx]);
 }
 
        return &(c->methods[idx]);
 }
@@ -2800,6 +3381,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) {
@@ -2924,12 +3506,20 @@ methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
 
 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
 {
 
 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) {
        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;
        }
                methodinfo *m = class_findmethod(c, name, desc);
                if (m) return m;
                /* search superclass */
                c = c->super;
        }
+       /*log_text("method not found:");*/
 
        return NULL;
 }
 
        return NULL;
 }
@@ -2979,30 +3569,33 @@ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
-       if ((c->flags & ACC_INTERFACE) == 0) {
+       if (!(c->flags & ACC_INTERFACE)) {
                if (except)
                if (except)
-                       *exceptionptr = new_exception("java/lang/IncompatibleClassChangeError");
+                       *exceptionptr =
+                               new_exception(string_java_lang_IncompatibleClassChangeError);
+
                return NULL;
        }
 
                return NULL;
        }
 
-       mi = class_resolveinterfacemethod_int(c,name,desc);
+       mi = class_resolveinterfacemethod_int(c, name, desc);
 
        if (mi)
 
        if (mi)
-               goto found;
+               return mi;
 
        /* try class java.lang.Object */
 
        /* try class java.lang.Object */
-       mi = class_findmethod(class_java_lang_Object,name,desc);
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+
        if (mi)
        if (mi)
-               goto found;
+               return mi;
 
        if (except)
 
        if (except)
-               *exceptionptr = new_exception("java/lang/NoSuchMethodError");
-       return NULL;
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
 
 
- found:
-       return mi;
+       return NULL;
 }
 
 }
 
+
 /********************* Function: class_resolveclassmethod *********************
        
     Resolves a reference from REFERER to a method with NAME and DESC in
 /********************* Function: class_resolveclassmethod *********************
        
     Resolves a reference from REFERER to a method with NAME and DESC in
@@ -3015,45 +3608,54 @@ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
 
 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
                                                                         classinfo *referer, bool except)
 
 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
                                                                         classinfo *referer, bool except)
-{
-       methodinfo *mi;
-       int i;
+{
        classinfo *cls;
        classinfo *cls;
-       
+       methodinfo *mi;
+       s4 i;
+       char msg[MAXLOGTEXT];
+
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
        /* XXX resolve class c */
        /* XXX check access from REFERER to C */
        
-       if ((c->flags & ACC_INTERFACE) != 0) {
-               if (except)
-                       *exceptionptr = new_exception("java/lang/IncompatibleClassChangeError");
-               return NULL;
-       }
+/*     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 {
 
        /* try class c and its superclasses */
        cls = c;
        do {
-               mi = class_findmethod(cls,name,desc);
+               mi = class_findmethod(cls, name, desc);
                if (mi)
                        goto found;
        } while ((cls = cls->super) != NULL); /* try the superclass */
 
        /* try the superinterfaces */
                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);
+       for (i = 0; i < c->interfacescount; ++i) {
+               mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
                if (mi)
                        goto found;
        }
        
                if (mi)
                        goto found;
        }
        
-       if (except)
-               *exceptionptr = new_exception("java/lang/NoSuchMethodError");
+       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;
 
  found:
        return NULL;
 
  found:
-       if ((mi->flags & ACC_ABSTRACT) != 0 &&
-               (c->flags & ACC_ABSTRACT) == 0) 
-       {
+       if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
                if (except)
                if (except)
-                       *exceptionptr = new_exception("java/lang/AbstractMethodError");
+                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+
                return NULL;
        }
 
                return NULL;
        }
 
@@ -3087,7 +3689,65 @@ 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;
+
+#if defined(USE_THREADS)
+       /* enter a monitor on the class */
+
+       builtin_monitorenter((java_objectheader *) c);
+#endif
+
+       /* maybe the class is already initalized or the current thread, which can
+          pass the monitor, is currently initalizing this class */
+
+       /* JOWENN: In future we need an additinal flag: initializationfailed,
+               since further access to the class should cause a NoClassDefFound,
+               if the static initializer failed once
+        */
+
+       if (c->initialized || c->initializing) {
+#if defined(USE_THREADS)
+               builtin_monitorexit((java_objectheader *) c);
+#endif
+
+               return c;
+       }
+
+       /* this initalizing run begins NOW */
+       c->initializing = true;
+
+       /* call the internal function */
+       r = class_init_intern(c);
+
+       /* if return value is not NULL everything was ok and the class is
+          initialized */
+       if (r)
+               c->initialized = true;
+
+       /* this initalizing run is done */
+       c->initializing = false;
+
+#if defined(USE_THREADS)
+       /* leave the monitor */
+
+       builtin_monitorexit((java_objectheader *) c);
+#endif
+
+       return r;
+}
+
+
+/* this function MUST NOT be called directly, because of thread <clinit>
+   race conditions */
+
+static classinfo *class_init_intern(classinfo *c)
 {
        methodinfo *m;
        s4 i;
 {
        methodinfo *m;
        s4 i;
@@ -3095,65 +3755,77 @@ void class_init(classinfo *c)
        int b;
 #endif
 
        int b;
 #endif
 
-       if (!makeinitializations)
-               return;
-       if (c->initialized)
-               return;
+       /* maybe the class is not already loaded */
+       if (!c->loaded)
+               if (!class_load(c))
+                       return NULL;
 
 
-       c->initialized = true;
+       /* maybe the class is not already linked */
+       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 */
 #endif
 
        /* initialize super class */
+
        if (c->super) {
        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->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 */
        }
 
        /* initialize interface classes */
+
        for (i = 0; i < c->interfacescount; i++) {
        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]->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_void__void);
+
        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!");
+       /* Sun's and IBM's JVM don't care about the static flag */
+/*     if (!(m->flags & ACC_STATIC)) { */
+/*             panic("Class initializer is not static!"); */
 
 
-       if (initverbose) {
-               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;
@@ -3168,66 +3840,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);
-
-               /* do we have a detail message? */
-               if (((java_lang_Throwable *) *exceptionptr)->detailMessage) {
-                       printf(": ");
-                       utf_display(javastring_toutf(((java_lang_Throwable *) *exceptionptr)->detailMessage, false));
-               }
+               /* class is NOT initialized */
+               c->initialized = false;
 
 
-               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);
-       }
+                       /* get the cause */
+                       cause = *exceptionptr;
 
 
-       if (c->name == utf_systemclass) {
-               /* class java.lang.System requires explicit initialization */
+                       /* clear exception, because we are calling jit code again */
+                       *exceptionptr = NULL;
 
 
-               if (initverbose)
-                       printf("#### Initializing class System");
+                       /* wrap the exception */
+                       xptr =
+                               new_exception_throwable(string_java_lang_ExceptionInInitializerError,
+                                                                               (java_lang_Throwable *) cause);
 
 
-                /* find initializing method */
-               m = class_findmethod(c,
-                                                        utf_initsystemclass,
-                                                        utf_fidesc);
+                       /* XXX should we exit here? */
+                       if (*exceptionptr)
+                               throw_exception();
 
 
-               if (!m) {
-                       /* no method found */
-                       /* printf("initializeSystemClass failed"); */
-                       return;
+                       /* set new exception */
+                       *exceptionptr = xptr;
                }
 
                }
 
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-               b = blockInts;
-               blockInts = 0;
-#endif
-
-               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;
 }
 
 
 }
 
 
@@ -3480,211 +4128,56 @@ 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;
-
-       /* avoid recursive calls */
-       if (loader_load_running)
-               return class_new(topname);
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       compiler_lock();
-#endif
-
-       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)
-                                       *exceptionptr = new_exception_utfmessage(string_java_lang_LinkageError,
-                                                                                                                        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)");
-                       
-                       new_exception_utfmessage(string_java_lang_NoClassDefFoundError,
-                                                                        top->name);
-                       top = NULL;
-                       
-               } else if (!top->linked) {
-                       if (linkverbose)
-                               dolog("Failed to link class (former call)");
-
-                       new_exception_utfmessage(string_java_lang_LinkageError,
-                                                                        top->name);
-                       top = NULL;
-               }
-       }
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsRestore();
-#endif
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       compiler_unlock();
-#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()
+static bool create_primitive_classes()
 {  
 {  
-       int i;
+       s4 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;
+               if (!class_link(c))
+                       return false;
 
                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)
+                               if (!class_link(c))
+                                       return false;
                        primitivetype_table[i].arrayvftbl = c->vftbl;
                }
        }
                        primitivetype_table[i].arrayvftbl = c->vftbl;
                }
        }
+
+       return true;
 }
 
 }
 
+
 /**************** 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
@@ -3750,7 +4243,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)
@@ -3791,8 +4284,19 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                  case '[':
                          if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
                          name = utf_new(start, utf_ptr - start);
                  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 */
+                         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 */
+                         }
                }
        }
 
                }
        }
 
@@ -3864,39 +4368,28 @@ 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->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->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->loaded = true;
+       pseudo_class_New->linked = true;
+       pseudo_class_New->super = class_java_lang_Object;
 }
 
 
 }
 
 
@@ -3907,53 +4400,41 @@ static void create_pseudo_classes()
 
 *******************************************************************************/
  
 
 *******************************************************************************/
  
-void loader_init(u1 *stackbottom)
+bool loader_init(u1 *stackbottom)
 {
 {
+       classpath_info *cpi;
+
+       /* reset interface index */
+
        interfaceindex = 0;
        
        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");
-       utf_code             = utf_new_char("Code");
-       utf_exceptions      = utf_new_char("Exceptions");
-       utf_linenumbertable     = utf_new_char("LineNumberTable");
-       utf_sourcefile          = utf_new_char("SourceFile");
-       utf_finalize        = utf_new_char("finalize");
-       utf_fidesc              = utf_new_char("()V");
-       utf_init                = utf_new_char("<init>");
-       utf_clinit              = utf_new_char("<clinit>");
-       utf_initsystemclass = utf_new_char("initializeSystemClass");
-       utf_systemclass     = utf_new_char("java/lang/System");
-       utf_vmclassloader   = utf_new_char("java/lang/VMClassLoader");
-       utf_initialize      = utf_new_char("initialize");
-       utf_initializedesc  = utf_new_char("(I)V");
-
-       utf_vmclass         = utf_new_char("java/lang/VMClass");
-       utf_java_lang_Object= utf_new_char("java/lang/Object");
-
-       array_packagename   = utf_new_char("<the array package>");
-
-       /* 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 defined(USE_THREADS) && defined(NATIVE_THREADS)
+       /* Initialize the monitor pointer for zip/jar file locking.               */
+
+       for (cpi = classpath_entries; cpi != NULL; cpi = cpi->next) {
+               if (cpi->type == CLASSPATH_ARCHIVE) 
+                       initObjectLock(&cpi->header);
+       }
+#endif
 
 
-       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);
+       /* Create some important classes. These classes have to be created now    */
+       /* because the classinfo pointers are used in the loading code.           */
+
+       if (!class_load(class_java_lang_Object) ||
+               !class_link(class_java_lang_Object))
+               return false;
+
+       if (!class_load(class_java_lang_String) ||
+               !class_link(class_java_lang_String))
+               return false;
 
 
-       loader_inited = 1; /*JOWENN*/
+       if (!class_load(class_java_lang_Cloneable) ||
+               !class_link(class_java_lang_Cloneable))
+               return false;
 
 
-       loader_load_sysclass(&class_java_lang_Throwable,
-                                                utf_new_char("java/lang/Throwable"));
+       if (!class_load(class_java_io_Serializable) ||
+               !class_link(class_java_io_Serializable))
+               return false;
 
        /* create classes representing primitive types */
        create_primitive_classes();
 
        /* create classes representing primitive types */
        create_primitive_classes();
@@ -3965,127 +4446,82 @@ void loader_init(u1 *stackbottom)
        stringtable_update();
 
 #if defined(USE_THREADS)
        stringtable_update();
 
 #if defined(USE_THREADS)
-       if (stackbottom!=0)
+       if (stackbottom != 0)
                initLocks();
 #endif
 
                initLocks();
 #endif
 
-       loader_inited = 1;
+       return true;
 }
 
 
 }
 
 
-/********************* Function: loader_initclasses ****************************
+/* loader_compute_subclasses ***************************************************
 
 
-       Initializes all loaded but uninitialized classes
+   XXX
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-#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);
-               }
-       }
+static void loader_compute_class_values(classinfo *c);
 
 
-       intsRestore();                      /* schani */
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
+void loader_compute_subclasses(classinfo *c)
+{
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+#else
+       intsDisable();
 #endif
 #endif
-}
 #endif
 
 #endif
 
-
-static void loader_compute_class_values(classinfo *c)
-{
-       classinfo *subs;
-
-       c->vftbl->baseval = ++classvalue;
-
-       subs = c->sub;
-       while (subs != NULL) {
-               loader_compute_class_values(subs);
-               subs = subs->nextsub;
+       if (!(c->flags & ACC_INTERFACE)) {
+               c->nextsub = 0;
+               c->sub = 0;
        }
        }
-       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");
+
+       if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
+               c->nextsub = c->super->sub;
+               c->super->sub = c;
        }
        }
-*/     
-}
 
 
+       classvalue = 0;
 
 
-void loader_compute_subclasses()
-{
-       classinfo *c;
-       
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsDisable();                     /* schani */
-#endif
+       /* this is the java.lang.Object special case */
 
 
-       c = list_first(&linkedclasses);
-       while (c) {
-               if (!(c->flags & ACC_INTERFACE)) {
-                       c->nextsub = 0;
-                       c->sub = 0;
-               }
-               c = list_next(&linkedclasses, c);
-       }
+       if (!class_java_lang_Object) {
+               loader_compute_class_values(c);
 
 
-       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);
+       } else {
+               loader_compute_class_values(class_java_lang_Object);
        }
 
        }
 
-       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();
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_unlock();
+#else
+       intsRestore();
 #endif
 #endif
-
-#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
-       intsRestore();                      /* schani */
 #endif
 }
 
 
 #endif
 }
 
 
-/******************** function classloader_buffer ******************************
-    sets buffer for reading classdata
+/* loader_compute_class_values *************************************************
+
+   XXX
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-void classload_buffer(u1 *buf, int len)
+static void loader_compute_class_values(classinfo *c)
 {
 {
-       classbuffer      = buf;
-       classbuffer_size = len;
-       classbuf_pos     = buf - 1;
+       classinfo *subs;
+
+       c->vftbl->baseval = ++classvalue;
+
+       subs = c->sub;
+       while (subs) {
+               loader_compute_class_values(subs);
+               subs = subs->nextsub;
+       }
+
+       c->vftbl->diffval = classvalue - c->vftbl->baseval;
 }
 
 
 }
 
 
@@ -4098,18 +4534,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;
+               }
        }
 }
 
        }
 }