Calling convention fixes.
[cacao.git] / src / vm / loader.c
index c7c50c795407fa0c0ddfdb53a77a9d299cfafd04..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 864 2004-01-07 18:51:16Z 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 <sys/stat.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
+
+#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
 
 #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_finalize;                  /* finalize                */
-static utf *utf_fidesc;                    /* ()V changed             */
-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;
-
-/* stefan */
-/* These are made static so they cannot be used for throwing in native */
-/* functions.                                                          */
-static classinfo *class_java_lang_ClassCastException;
-static classinfo *class_java_lang_NullPointerException;
-static classinfo *class_java_lang_ArrayIndexOutOfBoundsException;
-static classinfo *class_java_lang_NegativeArraySizeException;
-static classinfo *class_java_lang_OutOfMemoryError;
-static classinfo *class_java_lang_ArithmeticException;
-static classinfo *class_java_lang_ArrayStoreException;
-static classinfo *class_java_lang_ThreadDeath;
-
-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;
 
 
 /******************************************************************************
 
 
 /******************************************************************************
@@ -168,17 +118,6 @@ primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
 };
 
 
 };
 
 
-/* instances of important system classes **************************************/
-
-java_objectheader *proto_java_lang_ClassCastException;
-java_objectheader *proto_java_lang_NullPointerException;
-java_objectheader *proto_java_lang_ArrayIndexOutOfBoundsException;
-java_objectheader *proto_java_lang_NegativeArraySizeException;
-java_objectheader *proto_java_lang_OutOfMemoryError;
-java_objectheader *proto_java_lang_ArithmeticException;
-java_objectheader *proto_java_lang_ArrayStoreException;
-java_objectheader *proto_java_lang_ThreadDeath;
-
 /************* functions for reading classdata *********************************
 
     getting classdata in blocks of variable size
 /************* functions for reading classdata *********************************
 
     getting classdata in blocks of variable size
@@ -186,104 +125,151 @@ java_objectheader *proto_java_lang_ThreadDeath;
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-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;
+}
+
+
+/* suck_nbytes *****************************************************************
+
+   transfer block of classfile data into a buffer
+
+*******************************************************************************/
+
+inline void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+       memcpy(buffer, cb->pos + 1, len);
+       cb->pos += len;
+}
+
 
 
-/* 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)
+/* skip_nbytes ****************************************************************
 
 
-/* transfer block of classfile data into a buffer */
+   skip block of classfile data
 
 
-#define suck_nbytes(buffer,len)                                                \
-       do {ASSERT_LEFT(len);                                                   \
-               memcpy(buffer,classbuf_pos+1,len);                      \
-               classbuf_pos+=len;} while (0)
+*******************************************************************************/
 
 
-/* skip block of classfile data */
+inline void skip_nbytes(classbuffer *cb, s4 len)
+{
+       cb->pos += len;
+}
 
 
-#define skip_nbytes(len)                                               \
-       do {ASSERT_LEFT(len);                                           \
-               classbuf_pos+=len;} while(0)
 
 
-inline u1 suck_u1()
+inline u1 suck_u1(classbuffer *cb)
 {
 {
-       ASSERT_LEFT(1);
-       return *++classbuf_pos;
+       return *++(cb->pos);
 }
 }
-inline u2 suck_u2()
+
+
+inline u2 suck_u2(classbuffer *cb)
 {
 {
-       u1 a=suck_u1(), b=suck_u1();
-       return ((u2)a<<8)+(u2)b;
+       u1 a = suck_u1(cb);
+       u1 b = suck_u1(cb);
+       return ((u2) a << 8) + (u2) b;
 }
 }
-inline u4 suck_u4()
+
+
+inline u4 suck_u4(classbuffer *cb)
 {
 {
-       u1 a=suck_u1(), b=suck_u1(), c=suck_u1(), d=suck_u1();
-       return ((u4)a<<24)+((u4)b<<16)+((u4)c<<8)+(u4)d;
+       u1 a = suck_u1(cb);
+       u1 b = suck_u1(cb);
+       u1 c = suck_u1(cb);
+       u1 d = suck_u1(cb);
+       return ((u4) a << 24) + ((u4) b << 16) + ((u4) c << 8) + (u4) d;
 }
 }
-#define suck_s8() (s8) suck_u8()
-#define suck_s2() (s2) suck_u2()
-#define suck_s4() (s4) suck_u4()
-#define suck_s1() (s1) suck_u1()
 
 
 /* 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;
 }
@@ -295,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
@@ -421,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;
+
+       /* initialize return value */
+
+       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 (classbuffer) return true; /* classbuffer is already valid */
-
-       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) {
+                       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.
@@ -512,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);
 }
 
 
 }
 
 
@@ -571,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])
@@ -633,60 +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;
+                       }
+
+                       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;
 }
 
 
 }
 
 
@@ -704,6 +821,8 @@ static void checkfielddescriptor (char *utf_ptr, char *end_pos)
                                                  | CLASSLOAD_NULLPRIMITIVE
                                                  | CLASSLOAD_NOVOID
                                                  | CLASSLOAD_CHECKEND);
                                                  | CLASSLOAD_NULLPRIMITIVE
                                                  | CLASSLOAD_NOVOID
                                                  | CLASSLOAD_CHECKEND);
+       
+       /* XXX use the following if -noverify */
 #if 0
        char *tstart;  /* pointer to start of classname */
        char ch;
 #if 0
        char *tstart;  /* pointer to start of classname */
        char ch;
@@ -741,35 +860,62 @@ static void checkfielddescriptor (char *utf_ptr, char *end_pos)
 
     checks whether a method-descriptor is valid and aborts otherwise.
     All referenced classes are inserted into the list of unloaded classes.
 
     checks whether a method-descriptor is valid and aborts otherwise.
     All referenced classes are inserted into the list of unloaded classes.
+
+    The number of arguments is returned. A long or double argument is counted
+    as two arguments.
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-static void 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       */
+       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 != ')') {
+               /* We cannot count the this argument here because
+                * we don't know if the method is static. */
+               if (*utf_ptr == 'J' || *utf_ptr == 'D')
+                       argcount+=2;
+               else
+                       argcount++;
                class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
                                                          CLASSLOAD_NEW
                                                          | CLASSLOAD_NULLPRIMITIVE
                                                          | CLASSLOAD_NOVOID);
        }
 
                class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
                                                          CLASSLOAD_NEW
                                                          | CLASSLOAD_NULLPRIMITIVE
                                                          | CLASSLOAD_NOVOID);
        }
 
-       if (utf_ptr == end_pos) panic("Missing return type in method descriptor");
+       if (utf_ptr == end_pos)
+               panic("Missing ')' in method descriptor");
+
     utf_ptr++; /* skip ')' */
 
     utf_ptr++; /* skip ')' */
 
-       class_from_descriptor(utf_ptr,end_pos,NULL,
-                                                 CLASSLOAD_NEW
-                                                 | CLASSLOAD_NULLPRIMITIVE
-                                                 | CLASSLOAD_CHECKEND);
-       
+       class_from_descriptor(utf_ptr,
+                                                 end_pos,
+                                                 NULL,
+                                                 CLASSLOAD_NEW |
+                                                 CLASSLOAD_NULLPRIMITIVE |
+                                                 CLASSLOAD_CHECKEND);
+
+       if (argcount > 255) {
+               *exceptionptr =
+                       new_classformaterror(c, "Too many arguments in signature");
+
+               return 0;
+       }
+
+       return argcount;
+
+       /* XXX use the following if -noverify */
 #if 0
 #if 0
-       /* XXX check length */
        /* check arguments */
        while ((c = *utf_ptr++) != ')') {
                start = utf_ptr-1;
        /* check arguments */
        while ((c = *utf_ptr++) != ')') {
                start = utf_ptr-1;
@@ -851,49 +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 */
-       f->type = jtype = desc_to_type(f->descriptor);                      /* data type         */
-       f->offset = 0;                                                            /* offset from start of object */
-       f->class = c;
-       f->xta = NULL;
-       
-       /* check flag consistency */
        if (opt_verify) {
        if (opt_verify) {
-               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");
+               /* 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) ||
+                       ((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 */
+               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->class = c;
+       f->xta = NULL;
+       
        switch (f->type) {
        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;
@@ -903,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 **********************************/
 
 }
 
 
 /********************** function: field_free **********************************/
 
-static void field_free (fieldinfo *f)
+static void field_free(fieldinfo *f)
 {
        /* empty */
 }
 {
        /* empty */
 }
@@ -994,70 +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;
-       static utf* name_init = NULL;
-       static utf* name_clinit = NULL;
-       
+       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->class = c;
        m->class = c;
+       m->nativelyoverloaded = false;
        
        
-       m->flags = suck_u2();
-       m->name = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
-       m->descriptor = class_getconstant(c, suck_u2(), CONSTANT_Utf8);
-       checkmethoddescriptor(m->descriptor);   
+       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;
 
 
-       /* check flag consistency */
        if (opt_verify) {
        if (opt_verify) {
-               if (!name_init) {
-                       name_init = utf_new_char("<init>");
-                       name_clinit = utf_new_char("<clinit>");
+               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");
+       }
+       
+       argcount = checkmethoddescriptor(c, m->descriptor);
+
+       if (!(m->flags & ACC_STATIC))
+               argcount++; /* count the 'this' argument */
+
+       if (opt_verify) {
+               if (argcount > 255) {
+                       *exceptionptr =
+                               new_classformaterror(c, "Too many arguments in signature");
+                       return false;
                }
                }
-               /* XXX could check if <clinit> is STATIC */
-               if (m->name != name_clinit) {
+
+               /* check flag consistency */
+               if (m->name != utf_clinit) {
                        i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
                        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 ((c->flags & ACC_INTERFACE) != 0) {
-                               if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC))
-                                       != (ACC_ABSTRACT | ACC_PUBLIC))
-                                       panic("Interface method is not declared abstract and public");
+
+                       if (m->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 (m->name == name_init) {
-                               if ((m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED
-                                                                | ACC_NATIVE | ACC_ABSTRACT)) != 0)
+
+                       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->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;
@@ -1069,73 +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 (!check_classbuffer_size(cb, 2))
+                       return false;
 
 
-               if (aname != utf_code) {
-                       skipattributebody();
+               if (!(aname = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+                       return false;
 
 
-               } else {
-                       u4 codelen;
-                       if ((m->flags & (ACC_ABSTRACT | ACC_NATIVE)) != 0)
-                               panic("Code attribute for native or abstract method");
+               if (aname == utf_Code) {
+                       if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
+                                       *exceptionptr =
+                                               new_classformaterror(c,
+                                                                                        "Code attribute in native or abstract methods");
+
+                                       return false;
+                       }
                        
                        
-                       if (m->jcode)
-                               panic("Method has more than one Code attribute");
-
-                       suck_u4();
-                       m->maxstack = suck_u2();
-                       m->maxlocals = suck_u2();
-                       codelen = suck_u4();
-                       if (codelen == 0)
-                               panic("bytecode has zero length");
-                       if (codelen > 65536)
-                               panic("bytecode too long");
-                       m->jcodelength = codelen;
+                       if (m->jcode) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Multiple Code attributes");
+
+                               return false;
+                       }
+
+                       if (!check_classbuffer_size(cb, 4 + 2 + 2))
+                               return false;
+
+                       suck_u4(cb);
+                       m->maxstack = suck_u2(cb);
+                       m->maxlocals = suck_u2(cb);
+
+                       if (m->maxlocals < argcount) {
+                               *exceptionptr =
+                                       new_classformaterror(c, "Arguments can't fit into locals");
+
+                               return false;
+                       }
+                       
+                       if (!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;
+                       }
+                       
+                       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 {
+                                       if (!(m->exceptiontable[j].catchtype =
+                                                 class_getconstant(c, idx, CONSTANT_Class)))
+                                               return false;
+                               }
+                       }
+
+                       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 {
 
                                } else {
-                                       m->exceptiontable[e].catchtype = 
-                                     class_getconstant(c, idx, CONSTANT_Class);
+                                       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;
 
 
-                       skipattributes(suck_u2());
+                       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;
 }
 
 
 }
 
 
@@ -1180,68 +1583,51 @@ void method_display(methodinfo *m)
        printf("\n");
 }
 
        printf("\n");
 }
 
+/************** Function: method_display_w_class  (debugging only) **************/
 
 
-/******************** Function: method_canoverwrite ****************************
-
-       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)
+void method_display_w_class(methodinfo *m)
 {
 {
-       if (m->name != old->name) return false;
-       if (m->descriptor != old->descriptor) return false;
-       if (m->flags & ACC_STATIC) return false;
-       return true;
+        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) **************/
 
 
-
-
-/******************************************************************************/
-/************************ 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)
+void method_display_flags_last(methodinfo *m)
 {
 {
-       /* 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];
+        printf(" ");
+        utf_display(m->name);
+        printf(" ");
+        utf_display(m->descriptor);
+        printf("   ");
+        printflags(m->flags);
+        printf("\n");
 }
 
 
 }
 
 
-/********************* Function: class_constanttype ****************************
+/******************** Function: method_canoverwrite ****************************
 
 
-       Determines the type of a class entry in the ConstantPool
+       Check if m and old are identical with respect to type and name. This means
+       that old can be overwritten with m.
        
 *******************************************************************************/
 
        
 *******************************************************************************/
 
-u4 class_constanttype(classinfo *c, u4 pos)
+static bool method_canoverwrite(methodinfo *m, methodinfo *old)
 {
 {
-       if (pos >= c->cpcount)
-               panic("Attempt to access constant outside range");
-
-       return c->cptags[pos];
+       if (m->name != old->name) return false;
+       if (m->descriptor != old->descriptor) return false;
+       if (m->flags & ACC_STATIC) return false;
+       return true;
 }
 
 
 }
 
 
@@ -1254,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 
@@ -1262,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;
 
@@ -1285,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;
@@ -1295,296 +1681,393 @@ 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 */
-       for (idx=0; idx<cpcount; idx++) {
+       for (idx = 0; idx < cpcount; idx++) {
                cptags[idx] = CONSTANT_UNUSED;
                cpinfos[idx] = NULL;
                cptags[idx] = CONSTANT_UNUSED;
                cpinfos[idx] = NULL;
-               }
+       }
 
                        
 
                        
-               /******* first pass *******/
-               /* entries which cannot be resolved now are written into 
-                  temporary structures and traversed again later        */
+       /******* first pass *******/
+       /* entries which cannot be resolved now are written into 
+          temporary structures and traversed again later        */
                   
        idx = 1;
        while (idx < cpcount) {
                   
        idx = 1;
        while (idx < cpcount) {
+               u4 t;
+
                /* get constant type */
                /* get constant type */
-               u4 t = suck_u1 (); 
-               switch ( t ) {
+               if (!check_classbuffer_size(cb, 1))
+                       return false;
 
 
-                       case CONSTANT_Class: { 
-                               forward_class *nfc = DNEW(forward_class);
+               t = suck_u1(cb);
 
 
-                               nfc -> next = forward_classes;                                                                                  
-                               forward_classes = nfc;
+               switch (t) {
+               case CONSTANT_Class:
+                       nfc = NEW(forward_class);
 
 
-                               nfc -> thisindex = idx;
-                               /* reference to CONSTANT_NameAndType */
-                               nfc -> name_index = suck_u2 (); 
+                       nfc->next = forward_classes;
+                       forward_classes = nfc;
 
 
-                               idx++;
-                               break;
-                               }
+                       nfc->thisindex = idx;
+                       /* reference to CONSTANT_NameAndType */
+                       if (!check_classbuffer_size(cb, 2))
+                               return false;
+
+                       nfc->name_index = suck_u2(cb);
+
+                       idx++;
+                       break;
                        
                        
-                       case CONSTANT_Fieldref:
-                       case CONSTANT_Methodref:
-                       case CONSTANT_InterfaceMethodref: { 
-                               forward_fieldmethint *nff = DNEW (forward_fieldmethint);
-                               
-                               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))
-                                       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);
 
 
-               cptags  [forward_classes -> thisindex] = CONSTANT_Class;
+               if (opt_verify && !is_valid_name_utf(name))
+                       panic("Class reference with invalid name");
+
+               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);
-                
-               cptags   [forward_nameandtypes -> thisindex] = CONSTANT_NameAndType;
-               cpinfos  [forward_nameandtypes -> thisindex] = cn;
-               
-               forward_nameandtypes = forward_nameandtypes -> next;
+               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 (!is_valid_name_utf(cn->name)) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
+
+                       /* disallow referencing <clinit> among others */
+                       if (cn->name->text[0] == '<' && cn->name != utf_init) {
+                               *exceptionptr =
+                                       new_exception_utfmessage(string_java_lang_InternalError,
+                                                                                        cn->name);
+                               return false;
+                       }
                }
 
                }
 
+               cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
+               cpinfos[forward_nameandtypes->thisindex] = cn;
 
 
-       while (forward_fieldmethints)  {
+               nfn = forward_nameandtypes;
+               forward_nameandtypes = forward_nameandtypes->next;
+               FREE(nfn, forward_nameandtype);
+       }
+
+       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 */
-                       /* XXX check special names (<init>) */
-                                        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;
 }
 
 
 }
 
 
@@ -1601,40 +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)) {
-               throw_noclassdeffounderror_message(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;
        }
        
        }
        
-       /* check signature */           
-       if (suck_u4() != MAGIC) panic("Can not find class-file signature");     
+       /* 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 */
+       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 (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;
        }
 
        }
 
-       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;     
@@ -1643,90 +2227,271 @@ 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)
-                       panic("Interface class not declared abstract");
-               if ((c->flags & (ACC_FINAL | ACC_SUPER)) != 0)
-                       panic("Interface class has invalid flags");
+       if (c->flags & ACC_INTERFACE) {
+               if (!(c->flags & ACC_ABSTRACT)) {
+                       /* We work around this because interfaces in JDK 1.1 are
+                        * not declared abstract. */
+
+                       c->flags |= ACC_ABSTRACT;
+                       /* panic("Interface class not declared abstract"); */
+               }
+
+               if (c->flags & ACC_FINAL) {
+                       *exceptionptr =
+                               new_classformaterror(c,
+                                                                        "Illegal class modifiers: 0x%X", c->flags);
+
+                       return NULL;
+               }
+
+               if (c->flags & ACC_SUPER) {
+                       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 (!check_classbuffer_size(cb, 2 + 2))
+               return NULL;
+
        /* this class */
        /* this class */
-       i = suck_u2();
-       if (class_getconstant(c, i, CONSTANT_Class) != c)
-               panic("Invalid this_class in class file");
+       i = suck_u2(cb);
+       if (!(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;
 
 
-               /* 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");
+               /* java.lang.Object may not have a super class. */
+               if (c->name == utf_java_lang_Object) {
+                       *exceptionptr =
+                               new_exception_message(string_java_lang_ClassFormatError,
+                                                                         "java.lang.Object with superclass");
+
+                       return NULL;
+               }
+
+               /* 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;
        }
 
        }
 
-#ifdef STATISTICS
-       count_class_infos += sizeof(classinfo*) * c->interfacescount;
-       count_class_infos += sizeof(fieldinfo) * c->fieldscount;
-       count_class_infos += sizeof(methodinfo) * c->methodscount;
+       /* Check if all fields and methods can be uniquely
+        * identified by (name,descriptor). */
+       if (opt_verify) {
+               /* We use a hash table here to avoid making the
+                * average case quadratic in # of methods, fields.
+                */
+               static int shift = 0;
+               u2 *hashtab;
+               u2 *next; /* for chaining colliding hash entries */
+               size_t len;
+               size_t hashlen;
+               u2 index;
+               u2 old;
+
+               /* Allocate hashtable */
+               len = c->methodscount;
+               if (len < c->fieldscount) len = c->fieldscount;
+               hashlen = 5 * len;
+               hashtab = MNEW(u2,(hashlen + len));
+               next = hashtab + hashlen;
+
+               /* Determine bitshift (to get good hash values) */
+               if (!shift) {
+                       len = sizeof(utf);
+                       while (len) {
+                               len >>= 1;
+                               shift++;
+                       }
+               }
+
+               /* Check fields */
+               memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
+               for (i = 0; i < c->fieldscount; ++i) {
+                       fieldinfo *fi = c->fields + i;
+
+                       /* It's ok if we lose bits here */
+                       index = ((((size_t) fi->name) +
+                                         ((size_t) fi->descriptor)) >> shift) % hashlen;
+
+                       if ((old = hashtab[index])) {
+                               old--;
+                               next[i] = old;
+                               do {
+                                       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]));
+                       }
+                       hashtab[index] = i + 1;
+               }
+               
+               /* Check methods */
+               memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
+
+               for (i = 0; i < c->methodscount; ++i) {
+                       methodinfo *mi = c->methods + i;
+
+                       /* It's ok if we lose bits here */
+                       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--;
+                               next[i] = old;
+                               do {
+                                       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]));
+                       }
+                       hashtab[index] = i + 1;
+               }
+               
+               MFREE(hashtab, u2, (hashlen + len));
+       }
+
+#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.
@@ -1738,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]);
@@ -1757,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]);
@@ -1821,11 +2583,6 @@ void class_new_array(classinfo *c)
        methodinfo *clone;
        int namelen;
 
        methodinfo *clone;
        int namelen;
 
-       /* XXX remove */ /* 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] != '[')
@@ -1833,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 */
@@ -1851,35 +2625,42 @@ 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); /* XXX use GC? */
-    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); /* XXX use GC? */
+       c->methods = MNEW(methodinfo, c->methodscount);
 
        clone = c->methods;
        memset(clone, 0, sizeof(methodinfo));
 
        clone = c->methods;
        memset(clone, 0, sizeof(methodinfo));
-       clone->flags = ACC_PUBLIC; /* XXX protected? */
+       clone->flags = ACC_PUBLIC;
        clone->name = utf_new_char("clone");
        clone->descriptor = utf_new_char("()Ljava/lang/Object;");
        clone->class = c;
        clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
        clone->name = utf_new_char("clone");
        clone->descriptor = utf_new_char("()Ljava/lang/Object;");
        clone->class = c;
        clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
-       clone->monoPoly = MONO; /* XXX should be poly? */
+       clone->monoPoly = MONO;
 
        /* 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;
 }
 
 
 }
 
 
@@ -1896,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);
@@ -1926,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)
@@ -1939,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;
@@ -1949,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;
@@ -2005,49 +2802,128 @@ 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;
+       }
+
+       /* 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;
+}
 
 
-*******************************************************************************/
 
 
-void class_link(classinfo *c)
+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;
+
+       if (linkverbose)
+               log_message_class("Linking class: ", c);
 
 
+       /* ok, this class is somewhat linked */
+       c->linked = true;
 
 
-       /*  check if all superclasses are already linked, if not put c at end of
-           unlinked list and return. Additionally initialize class fields.       */
+       arraydesc = NULL;
 
 
-       /*  check interfaces */
+       /* 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 (!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 */
 
 
-       if (super == NULL) {          /* class java.long.Object */
+       super = c->super;
+
+       if (super == NULL) {          /* class java.lang.Object */
                c->index = 0;
         c->classUsed = USED;     /* Object class is always used CO-RT*/
                c->impldBy = NULL;
                c->index = 0;
         c->classUsed = USED;     /* Object class is always used CO-RT*/
                c->impldBy = NULL;
@@ -2058,25 +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;
                }
 
                }
 
-               /* handle array classes */
-               /* The component class must have been linked already. */
-               if (c->name->text[0] == '[')
-                       if ((arraydesc = class_link_array(c)) == NULL) {
-                               list_remove(&unlinkedclasses, c);
-                               list_addlast(&unlinkedclasses, c);
-                               return; 
-                       }
+               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");
+               }
 
                /* Don't allow extending final classes */
 
                /* Don't allow extending final classes */
-               if ((super->flags & ACC_FINAL) != 0)
-                       panic("Trying to extend final class");
+               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 */
+               if (c->name->text[0] == '[')
+                       if (!(arraydesc = class_link_array(c)))
+                               return NULL;
+
                if (c->flags & ACC_INTERFACE)
                        c->index = interfaceindex++;
                else
                if (c->flags & ACC_INTERFACE)
                        c->index = interfaceindex++;
                else
@@ -2089,61 +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_FINAL) != 0)
-                                                       panic("Trying to overwrite final method");
-                                               m->vftblindex = sc->methods[j].vftblindex;
+                       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;
+
+                                               if (tc->methods[j].flags & ACC_FINAL) {
+                                                       /* class a overrides final method . */
+                                                       *exceptionptr =
+                                                               new_exception(string_java_lang_VerifyError);
+                                                       return NULL;
+                                               }
+                                               m->vftblindex = tc->methods[j].vftblindex;
                                                goto foundvftblindex;
                                        }
                                }
                                                goto foundvftblindex;
                                        }
                                }
-                               sc = sc->super;
+                               tc = tc->super;
                        }
                        }
+               notfoundvftblindex:
                        m->vftblindex = (vftbllength++);
                        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;
@@ -2175,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;
@@ -2187,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++) {
@@ -2198,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;
 }
 
 
 }
 
 
@@ -2238,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;
+                               }
                        }
                }
                        }
                }
+       }
 
 
-       MFREE (c -> cptags,  u1, c -> cpcount);
-       MFREE (c -> cpinfos, voidptr, c -> cpcount);
+       if (c->cptags)
+               MFREE(c->cptags, u1, c->cpcount);
+
+       if (c->cpinfos)
+               MFREE(c->cpinfos, voidptr, c->cpcount);
 }
 
 
 }
 
 
@@ -2285,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)
@@ -2310,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); */
 }
 
 
 }
 
 
@@ -2338,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]);                                                         
@@ -2351,138 +3253,120 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 }
 
 
 }
 
 
-/************************* Function: class_findmethod **************************
-       
-       Searches a 'classinfo' structure for a method having the given name and
-       type and returns the index in the class info structure.
-       If type is NULL, it is ignored.
+/****************** Function: class_resolvefield_int ***************************
+
+    This is an internally used helper function. Do not use this directly.
+
+       Tries to resolve a field having the given name and type.
+    If the field cannot be resolved, NULL is returned.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
 {
        s4 i;
 {
        s4 i;
-#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
-       char *buffer;                   
-       int buffer_len, pos;
-#endif
-#ifdef JOWENN_DEBUG1
+       fieldinfo *fi;
 
 
-       buffer_len = 
-               utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
-       
-       buffer = MNEW(char, buffer_len);
+       /* search for field in class c */
+       for (i = 0; i < c->fieldscount; i++) { 
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+                       return &(c->fields[i]);
+               }
+    }
 
 
-       strcpy(buffer, "class_findmethod: method:");
-       utf_sprint(buffer + strlen(buffer), name);
-       strcpy(buffer + strlen(buffer), ", desc: ");
-       utf_sprint(buffer + strlen(buffer), desc);
-       strcpy(buffer + strlen(buffer), ", classname: ");
-       utf_sprint(buffer + strlen(buffer), c->name);
-       
-       log_text(buffer);       
+       /* try superinterfaces recursively */
+       for (i = 0; i < c->interfacescount; ++i) {
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+               if (fi)
+                       return fi;
+       }
 
 
-       MFREE(buffer, char, buffer_len);
-#endif 
-       for (i = 0; i < c->methodscount; i++) {
-#ifdef JOWENN_DEBUG2
-               buffer_len = 
-                       utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
+       /* try superclass */
+       if (c->super)
+               return class_resolvefield_int(c->super, name, desc);
+
+       /* not found */
+       return NULL;
+}
+
+
+/********************* Function: class_resolvefield ***************************
        
        
-               buffer = MNEW(char, buffer_len);
+       Resolves a reference from REFERER to a field with NAME and DESC in class C.
 
 
-               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);
+    If the field cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
+                                                         classinfo *referer, bool except)
+{
+       fieldinfo *fi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
        
        
-               log_text(buffer);       
+       fi = class_resolvefield_int(c, name, desc);
 
 
-               MFREE(buffer, char, buffer_len);
-#endif 
-               
-               
-               if ((c->methods[i].name == name) && ((desc == NULL) ||
-                                                                                        (c->methods[i].descriptor == desc))) {
-                       return i;
-               }
+       if (!fi) {
+               if (except)
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
+                                                                                name);
+
+               return NULL;
        }
 
        }
 
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
+       /* XXX check access rights */
 
 
-       return -1;
+       return fi;
 }
 
 
 /************************* Function: class_findmethod **************************
        
        Searches a 'classinfo' structure for a method having the given name and
 }
 
 
 /************************* Function: class_findmethod **************************
        
        Searches a 'classinfo' structure for a method having the given name and
-       type.
+       type and returns the index in the class info structure.
        If type is NULL, it is ignored.
 
 *******************************************************************************/
 
        If type is NULL, it is ignored.
 
 *******************************************************************************/
 
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+s4 class_findmethodIndex(classinfo *c, utf *name, utf *desc)
 {
 {
-#if 0
        s4 i;
        s4 i;
-#if defined(JOWENN_DEBUG1) || defined(JOWENN_DEBUG2)
-       char *buffer;                   
-       int buffer_len, pos;
-#endif
-#ifdef JOWENN_DEBUG1
-
-       buffer_len = 
-               utf_strlen(name) + utf_strlen(desc) + utf_strlen(c->name) + 64;
-       
-       buffer = MNEW(char, buffer_len);
-
-       strcpy(buffer, "class_findmethod: method:");
-       utf_sprint(buffer + strlen(buffer), name);
-       strcpy(buffer + strlen(buffer), ", desc: ");
-       utf_sprint(buffer + strlen(buffer), desc);
-       strcpy(buffer + strlen(buffer), ", classname: ");
-       utf_sprint(buffer + strlen(buffer), c->name);
-       
-       log_text(buffer);       
 
 
-       MFREE(buffer, char, buffer_len);
-#endif 
        for (i = 0; i < c->methodscount; i++) {
        for (i = 0; i < c->methodscount; i++) {
-#ifdef JOWENN_DEBUG2
-               buffer_len = 
-                       utf_strlen(c->methods[i].name) + utf_strlen(c->methods[i].descriptor)+ 64;
-       
-               buffer = MNEW(char, buffer_len);
 
 
-               strcpy(buffer, "class_findmethod: comparing to method:");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].name);
-               strcpy(buffer + strlen(buffer), ", desc: ");
-               utf_sprint(buffer + strlen(buffer), c->methods[i].descriptor);
-       
-               log_text(buffer);       
+/*             utf_display_classname(c->name);printf("."); */
+/*             utf_display(c->methods[i].name);printf("."); */
+/*             utf_display(c->methods[i].descriptor); */
+/*             printf("\n"); */
 
 
-               MFREE(buffer, char, buffer_len);
-#endif 
-               
                if ((c->methods[i].name == name) && ((desc == NULL) ||
                                                                                         (c->methods[i].descriptor == desc))) {
                if ((c->methods[i].name == name) && ((desc == NULL) ||
                                                                                         (c->methods[i].descriptor == desc))) {
-                       return &(c->methods[i]);
+                       return i;
                }
        }
                }
        }
-#ifdef JOWENN_DEBUG2   
-       class_showconstantpool(c);
-       log_text("class_findmethod: returning NULL");
-#endif
-       return NULL;
-#endif
 
 
-       s4 idx=class_findmethodIndex(c, name, desc);
-/*     if (idx==-1) log_text("class_findmethod: method not found");*/
-       if (idx == -1) return NULL;
+       return -1;
+}
+
+
+/************************* Function: class_findmethod **************************
+       
+       Searches a 'classinfo' structure for a method having the given name and
+       type.
+       If type is NULL, it is ignored.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+{
+       s4 idx = class_findmethodIndex(c, name, desc);
+
+       if (idx == -1)
+               return NULL;
 
        return &(c->methods[idx]);
 }
 
        return &(c->methods[idx]);
 }
@@ -2497,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) {
@@ -2510,6 +3395,42 @@ methodinfo *class_fetchmethod(classinfo *c, utf *name, utf *desc)
 }
 
 
 }
 
 
+/*********************** Function: class_findmethod_w**************************
+
+    like class_findmethod, but logs a warning if the method is not found
+
+*******************************************************************************/
+
+methodinfo *class_findmethod_w(classinfo *c, utf *name, utf *desc, char *from)
+{
+        methodinfo *mi;
+        mi = class_findmethod(c, name, desc);
+
+        if (!mi) {
+                log_plain("Class: "); if (c) log_plain_utf(c->name); log_nl();
+                log_plain("Method: "); if (name) log_plain_utf(name); log_nl();
+                log_plain("Descriptor: "); if (desc) log_plain_utf(desc); log_nl();
+
+                       if ( c->flags & ACC_PUBLIC )       log_plain(" PUBLIC ");
+               if ( c->flags & ACC_PRIVATE )      log_plain(" PRIVATE ");
+               if ( c->flags & ACC_PROTECTED )    log_plain(" PROTECTED ");
+               if ( c->flags & ACC_STATIC )       log_plain(" STATIC ");
+               if ( c->flags & ACC_FINAL )        log_plain(" FINAL ");
+               if ( c->flags & ACC_SYNCHRONIZED ) log_plain(" SYNCHRONIZED ");
+               if ( c->flags & ACC_VOLATILE )     log_plain(" VOLATILE ");
+               if ( c->flags & ACC_TRANSIENT )    log_plain(" TRANSIENT ");
+               if ( c->flags & ACC_NATIVE )       log_plain(" NATIVE ");
+               if ( c->flags & ACC_INTERFACE )    log_plain(" INTERFACE ");
+               if ( c->flags & ACC_ABSTRACT )     log_plain(" ABSTRACT ");
+
+               log_plain(from); 
+                log_plain(" : WARNING: Method not found");log_nl( );
+        }
+
+        return mi;
+}
+
+
 /************************* Function: class_findmethod_approx ******************
        
        like class_findmethod but ignores the return value when comparing the
 /************************* Function: class_findmethod_approx ******************
        
        like class_findmethod but ignores the return value when comparing the
@@ -2577,22 +3498,170 @@ methodinfo *class_resolvemethod_approx(classinfo *c, utf *name, utf *desc)
 }
 
 
 }
 
 
-/************************* Function: class_resolvemethod ***********************
+/************************* Function: class_resolvemethod ***********************
+       
+       Searches a class and every super class for a method.
+
+*******************************************************************************/
+
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+{
+       /*log_text("Trying to resolve a method");
+       utf_display(c->name);
+       utf_display(name);
+       utf_display(desc);*/
+
+       while (c) {
+               /*log_text("Looking in:");
+               utf_display(c->name);*/
+               methodinfo *m = class_findmethod(c, name, desc);
+               if (m) return m;
+               /* search superclass */
+               c = c->super;
+       }
+       /*log_text("method not found:");*/
+
+       return NULL;
+}
+
+
+/****************** Function: class_resolveinterfacemethod_int ****************
+
+    Internally used helper function. Do not use this directly.
+
+*******************************************************************************/
+
+static
+methodinfo *class_resolveinterfacemethod_int(classinfo *c, utf *name, utf *desc)
+{
+       methodinfo *mi;
+       int i;
+       
+       mi = class_findmethod(c,name,desc);
+       if (mi)
+               return mi;
+
+       /* try the superinterfaces */
+       for (i=0; i<c->interfacescount; ++i) {
+               mi = class_resolveinterfacemethod_int(c->interfaces[i],name,desc);
+               if (mi)
+                       return mi;
+       }
+       
+       return NULL;
+}
+
+/******************** Function: class_resolveinterfacemethod ******************
+
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    interface C.
+
+    If the method cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+                                                                                classinfo *referer, bool except)
+{
+       methodinfo *mi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+       if (!(c->flags & ACC_INTERFACE)) {
+               if (except)
+                       *exceptionptr =
+                               new_exception(string_java_lang_IncompatibleClassChangeError);
+
+               return NULL;
+       }
+
+       mi = class_resolveinterfacemethod_int(c, name, desc);
+
+       if (mi)
+               return mi;
+
+       /* try class java.lang.Object */
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+
+       if (mi)
+               return mi;
+
+       if (except)
+               *exceptionptr =
+                       new_exception_utfmessage(string_java_lang_NoSuchMethodError, name);
+
+       return NULL;
+}
+
+
+/********************* Function: class_resolveclassmethod *********************
        
        
-       Searches a class and every super class for a method.
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    class C.
+
+    If the method cannot be resolved the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
 
 *******************************************************************************/
 
 
 *******************************************************************************/
 
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+                                                                        classinfo *referer, bool except)
 {
 {
-       while (c) {
-               methodinfo *m = class_findmethod(c, name, desc);
-               if (m) return m;
-               /* search superclass */
-               c = c->super;
+       classinfo *cls;
+       methodinfo *mi;
+       s4 i;
+       char msg[MAXLOGTEXT];
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+/*     if (c->flags & ACC_INTERFACE) { */
+/*             if (except) */
+/*                     *exceptionptr = */
+/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
+/*             return NULL; */
+/*     } */
+
+       /* try class c and its superclasses */
+       cls = c;
+       do {
+               mi = class_findmethod(cls, name, desc);
+               if (mi)
+                       goto found;
+       } while ((cls = cls->super) != NULL); /* try the superclass */
+
+       /* try the superinterfaces */
+       for (i = 0; i < c->interfacescount; ++i) {
+               mi = class_resolveinterfacemethod_int(c->interfaces[i], name, desc);
+               if (mi)
+                       goto found;
+       }
+       
+       if (except) {
+               utf_sprint(msg, c->name);
+               sprintf(msg + strlen(msg), ".");
+               utf_sprint(msg + strlen(msg), name);
+               utf_sprint(msg + strlen(msg), desc);
+
+               *exceptionptr =
+                       new_exception_message(string_java_lang_NoSuchMethodError, msg);
        }
 
        return NULL;
        }
 
        return NULL;
+
+ found:
+       if ((mi->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+               if (except)
+                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+
+               return NULL;
+       }
+
+       /* XXX check access rights */
+
+       return mi;
 }
 
 
 }
 
 
@@ -2620,75 +3689,145 @@ 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;
-#ifdef USE_THREADS
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        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);
 
 
-#ifdef USE_THREADS
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        b = blockInts;
        blockInts = 0;
 #endif
        b = blockInts;
        blockInts = 0;
 #endif
@@ -2696,64 +3835,47 @@ void class_init(classinfo *c)
        /* now call the initializer */
        asm_calljavafunction(m, NULL, NULL, NULL, NULL);
 
        /* now call the initializer */
        asm_calljavafunction(m, NULL, NULL, NULL, NULL);
 
-#ifdef USE_THREADS
+#if defined(USE_THREADS) && !defined(NATIVE_THREADS)
        assert(blockInts == 0);
        blockInts = b;
 #endif
 
        assert(blockInts == 0);
        blockInts = b;
 #endif
 
-       /* we have to throw an exception */
+       /* we have an exception or error */
        if (*exceptionptr) {
        if (*exceptionptr) {
-               printf("Exception in thread \"main\" java.lang.ExceptionInInitializerError\n");
-               printf("Caused by: ");
-               utf_display((*exceptionptr)->vftbl->class->name);
-               printf("\n");
-               fflush(stdout);
-               exit(1);
-       }
+               /* class is NOT initialized */
+               c->initialized = false;
 
 
-       if (initverbose) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Finished initializer for class: ");
-               utf_sprint(logtext + strlen(logtext), c->name);
-               log_text(logtext);
-       }
+               /* is this an exception, than wrap it */
+               if (builtin_instanceof(*exceptionptr, class_java_lang_Exception)) {
+                       java_objectheader *xptr;
+                       java_objectheader *cause;
 
 
-       if (c->name == utf_systemclass) {
-               /* class java.lang.System requires explicit initialization */
+                       /* get the cause */
+                       cause = *exceptionptr;
 
 
-               if (initverbose)
-                       printf("#### Initializing class System");
+                       /* clear exception, because we are calling jit code again */
+                       *exceptionptr = NULL;
 
 
-                /* find initializing method */
-               m = class_findmethod(c,
-                                                        utf_initsystemclass,
-                                                        utf_fidesc);
+                       /* wrap the exception */
+                       xptr =
+                               new_exception_throwable(string_java_lang_ExceptionInInitializerError,
+                                                                               (java_lang_Throwable *) cause);
 
 
-               if (!m) {
-                       /* no method found */
-                       /* printf("initializeSystemClass failed"); */
-                       return;
-               }
+                       /* XXX should we exit here? */
+                       if (*exceptionptr)
+                               throw_exception();
 
 
-#ifdef USE_THREADS
-               b = blockInts;
-               blockInts = 0;
-#endif
+                       /* set new exception */
+                       *exceptionptr = xptr;
+               }
 
 
-               asm_calljavafunction(m, NULL, NULL, NULL, NULL);
+               return NULL;
+       }
 
 
-#ifdef USE_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;
 }
 
 
 }
 
 
@@ -3006,201 +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;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_lock(&compiler_mutex);
-#endif
-
-       /* avoid recursive calls */
-       if (loader_load_running)
-               return class_new(topname);
-
-       loader_load_running++;
-       
-       intsDisable();
-
-       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...");
-
-       /* XXX added a hack to break infinite linking loops. A better
-        * linking algorithm would be nice. -Edwin */
-       notlinkable = NULL;
-       while ((c = list_first(&unlinkedclasses))) {
-               class_link(c);
-               if (!c->linked) {
-                       if (!notlinkable)
-                               notlinkable = c;
-                       else if (notlinkable == c) {
-                               /* We tried to link this class for the second time and
-                                * no other classes were linked in between, so we are
-                                * caught in a loop.
-                                */
-                               if (linkverbose)
-                                       dolog("Cannot resolve linking dependencies");
-                               top = NULL;
-                               if (!*exceptionptr)
-                                       throw_linkageerror_message(c->name);
-                               break;
-                       }
-
-               } else
-                       notlinkable = NULL;
-       }
-       if (linkverbose)
-               dolog("Linking done.");
-
-       if (loader_inited)
-               loader_compute_subclasses();
-
-       /* measure time */
-       if (getloadingtime) {
-               stoptime = getcputime();
-               loadingtime += (stoptime - starttime);
-       }
-
-
-       loader_load_running--;
-       
-       /* check if a former loader_load call tried to load/link the class and 
-          failed. This is needed because the class didn't appear in the 
-          undloadclasses or unlinkedclasses list during this class. */
-       if (top) {
-               if (!top->loaded) {
-                       if (linkverbose) dolog("Failed to load class (former call)");
-                       throw_noclassdeffounderror_message(top->name);
-                       top = NULL;
-                       
-               } else if (!top->linked) {
-                       if (linkverbose)
-                               dolog("Failed to link class (former call)");
-                       throw_linkageerror_message(top->name);
-                       top = NULL;
-               }
-       }
-
-       intsRestore();
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
-#endif
-
-       /* XXX 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
@@ -3266,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)
@@ -3275,7 +4252,7 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
        bool error = false;
        utf *name;
 
        bool error = false;
        utf *name;
 
-       SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,error);
+       SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
 
        if (mode & CLASSLOAD_CHECKEND)
                error |= (utf_ptr != end_ptr);
 
        if (mode & CLASSLOAD_CHECKEND)
                error |= (utf_ptr != end_ptr);
@@ -3306,9 +4283,20 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                          /* FALLTHROUGH! */
                  case '[':
                          if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
                          /* FALLTHROUGH! */
                  case '[':
                          if (mode & CLASSLOAD_SKIP) return class_java_lang_Object;
-                         name = utf_new(start,utf_ptr-start);
-                         return (mode & CLASSLOAD_LOAD)
-                                 ? loader_load(name) : class_new(name); /* XXX */
+                         name = utf_new(start, utf_ptr - start);
+                         if (opt_eager) {
+                                 classinfo *tc;
+
+                                 tc = class_new_intern(name);
+                                 class_load(tc);
+                                 list_addfirst(&unlinkedclasses, tc);
+
+                                 return tc;
+
+                         } else {
+                                 return (mode & CLASSLOAD_LOAD)
+                                         ? class_load(class_new(name)) : class_new(name); /* XXX handle errors */
+                         }
                }
        }
 
                }
        }
 
@@ -3317,7 +4305,7 @@ classinfo *class_from_descriptor(char *utf_ptr, char *end_ptr,
                return NULL;
 
        log_plain("Invalid descriptor at beginning of '");
                return NULL;
 
        log_plain("Invalid descriptor at beginning of '");
-       log_plain_utf(utf_new(start, end_ptr-start));
+       log_plain_utf(utf_new(start, end_ptr - start));
        log_plain("'");
        log_nl();
                                                  
        log_plain("'");
        log_nl();
                                                  
@@ -3380,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;
 }
 
 
 }
 
 
@@ -3423,66 +4400,42 @@ 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_finalize        = utf_new_char("finalize");
-       utf_fidesc              = utf_new_char("()V");
-       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");
-
-       /* create some important classes */
-       /* These classes have to be created now because the classinfo
-        * pointers are used in the loading code.
-        */
-       class_java_lang_Object = class_new(utf_new_char("java/lang/Object"));
-       class_java_lang_String = class_new(utf_new_char("java/lang/String"));
-       class_java_lang_Cloneable = class_new(utf_new_char("java/lang/Cloneable"));
-       class_java_io_Serializable = class_new(utf_new_char("java/io/Serializable"));
-
-       if (verbose) log_text("loader_init: java/lang/Object");
-       /* load the classes which were created above */
-       loader_load_sysclass(NULL, class_java_lang_Object->name);
-
-       loader_inited = 1; /*JOWENN*/
-
-       loader_load_sysclass(&class_java_lang_Throwable,
-                                                utf_new_char("java/lang/Throwable"));
-
-       if (verbose) log_text("loader_init:  loader_load: java/lang/ClassCastException");
-       loader_load_sysclass(&class_java_lang_ClassCastException,
-                                                utf_new_char ("java/lang/ClassCastException"));
-       loader_load_sysclass(&class_java_lang_NullPointerException,
-                                                utf_new_char ("java/lang/NullPointerException"));
-       loader_load_sysclass(&class_java_lang_ArrayIndexOutOfBoundsException,
-                                                utf_new_char ("java/lang/ArrayIndexOutOfBoundsException"));
-       loader_load_sysclass(&class_java_lang_NegativeArraySizeException,
-                                                utf_new_char ("java/lang/NegativeArraySizeException"));
-       loader_load_sysclass(&class_java_lang_OutOfMemoryError,
-                                                utf_new_char ("java/lang/OutOfMemoryError"));
-       loader_load_sysclass(&class_java_lang_ArrayStoreException,
-                                                utf_new_char ("java/lang/ArrayStoreException"));
-       loader_load_sysclass(&class_java_lang_ArithmeticException,
-                                                utf_new_char ("java/lang/ArithmeticException"));
-       loader_load_sysclass(&class_java_lang_ThreadDeath,
-                                                utf_new_char ("java/lang/ThreadDeath"));
-               
+#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
+
+       /* 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;
+
+       if (!class_load(class_java_lang_Cloneable) ||
+               !class_link(class_java_lang_Cloneable))
+               return false;
+
+       if (!class_load(class_java_io_Serializable) ||
+               !class_link(class_java_io_Serializable))
+               return false;
+
        /* create classes representing primitive types */
        create_primitive_classes();
 
        /* create classes representing primitive types */
        create_primitive_classes();
 
@@ -3492,77 +4445,69 @@ void loader_init(u1 *stackbottom)
        /* correct vftbl-entries (retarded loading of class java/lang/String) */
        stringtable_update();
 
        /* correct vftbl-entries (retarded loading of class java/lang/String) */
        stringtable_update();
 
-#ifdef USE_THREADS
-       if (stackbottom!=0)
+#if defined(USE_THREADS)
+       if (stackbottom != 0)
                initLocks();
 #endif
 
                initLocks();
 #endif
 
-       if (verbose) log_text("loader_init: creating global proto_java_lang_ClassCastException");
-       proto_java_lang_ClassCastException =
-               builtin_new(class_java_lang_ClassCastException);
-
-       if (verbose) log_text("loader_init: proto_java_lang_ClassCastException has been initialized");
+       return true;
+}
 
 
-       proto_java_lang_NullPointerException =
-               builtin_new(class_java_lang_NullPointerException);
-       if (verbose) log_text("loader_init: proto_java_lang_NullPointerException has been initialized");
 
 
-       proto_java_lang_ArrayIndexOutOfBoundsException =
-               builtin_new(class_java_lang_ArrayIndexOutOfBoundsException);
+/* loader_compute_subclasses ***************************************************
 
 
-       proto_java_lang_NegativeArraySizeException =
-               builtin_new(class_java_lang_NegativeArraySizeException);
+   XXX
 
 
-       proto_java_lang_OutOfMemoryError =
-               builtin_new(class_java_lang_OutOfMemoryError);
+*******************************************************************************/
 
 
-       proto_java_lang_ArithmeticException =
-               builtin_new(class_java_lang_ArithmeticException);
+static void loader_compute_class_values(classinfo *c);
 
 
-       proto_java_lang_ArrayStoreException =
-               builtin_new(class_java_lang_ArrayStoreException);
+void loader_compute_subclasses(classinfo *c)
+{
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+#else
+       intsDisable();
+#endif
+#endif
 
 
-       proto_java_lang_ThreadDeath =
-               builtin_new(class_java_lang_ThreadDeath);
+       if (!(c->flags & ACC_INTERFACE)) {
+               c->nextsub = 0;
+               c->sub = 0;
+       }
 
 
-       loader_inited = 1;
-}
+       if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
+               c->nextsub = c->super->sub;
+               c->super->sub = c;
+       }
 
 
+       classvalue = 0;
 
 
-/********************* Function: loader_initclasses ****************************
+       /* this is the java.lang.Object special case */
 
 
-       Initializes all loaded but uninitialized classes
+       if (!class_java_lang_Object) {
+               loader_compute_class_values(c);
 
 
-*******************************************************************************/
+       } else {
+               loader_compute_class_values(class_java_lang_Object);
+       }
 
 
-#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);
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_unlock();
+#else
+       intsRestore();
+#endif
 #endif
 #endif
+}
 
 
-       intsDisable();                     /* schani */
 
 
-       if (makeinitializations) {
-               c = list_first(&linkedclasses);
-               while (c) {
-                       class_init(c);
-                       c = list_next(&linkedclasses, c);
-               }
-       }
+/* loader_compute_class_values *************************************************
 
 
-       intsRestore();                      /* schani */
-       
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       pthread_mutex_unlock(&compiler_mutex);
-#endif
-}
-#endif
+   XXX
 
 
+*******************************************************************************/
 
 static void loader_compute_class_values(classinfo *c)
 {
 
 static void loader_compute_class_values(classinfo *c)
 {
@@ -3571,73 +4516,12 @@ static void loader_compute_class_values(classinfo *c)
        c->vftbl->baseval = ++classvalue;
 
        subs = c->sub;
        c->vftbl->baseval = ++classvalue;
 
        subs = c->sub;
-       while (subs != NULL) {
+       while (subs) {
                loader_compute_class_values(subs);
                subs = subs->nextsub;
        }
                loader_compute_class_values(subs);
                subs = subs->nextsub;
        }
-       c->vftbl->diffval = classvalue - c->vftbl->baseval;
-       
-       /*
-       {
-       int i;
-       for (i = 0; i < c->index; i++)
-               printf(" ");
-       printf("%3d  %3d  ", (int) c->vftbl->baseval, c->vftbl->diffval);
-       utf_display(c->name);
-       printf("\n");
-       }
-       */
-}
-
-
-void loader_compute_subclasses()
-{
-       classinfo *c;
-       
-       intsDisable();                     /* schani */
-
-       c = list_first(&linkedclasses);
-       while (c) {
-               if (!(c->flags & ACC_INTERFACE)) {
-                       c->nextsub = 0;
-                       c->sub = 0;
-               }
-               c = list_next(&linkedclasses, 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);
-       }
-
-       classvalue = 0;
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       cast_lock();
-#endif
-       loader_compute_class_values(class_java_lang_Object);
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       cast_unlock();
-#endif
-
-       intsRestore();                      /* schani */
-}
-
-
-/******************** function classloader_buffer ******************************
-    sets buffer for reading classdata
-
-*******************************************************************************/
 
 
-void classload_buffer(u1 *buf, int len)
-{
-       classbuffer      = buf;
-       classbuffer_size = len;
-       classbuf_pos     = buf - 1;
+       c->vftbl->diffval = classvalue - c->vftbl->baseval;
 }
 
 
 }
 
 
@@ -3650,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;
+               }
        }
 }
 
        }
 }