This commit introduces C++ support.
[cacao.git] / src / vmcore / loader.c
index d7b90d98737ae5b6ea28af05a7aa09be1c043742..c303485d056611d5a8bd2e4d7b3103a0e5f530a2 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vmcore/loader.c - class loader functions
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -45,7 +43,9 @@
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
+#include "vm/package.hpp"
 #include "vm/primitive.h"
+#include "vm/resolve.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
 
@@ -89,13 +89,20 @@ static hashtable *hashtable_classloader;
    Initializes the classpath list and loads classes required for the
    primitive table.
 
+   NOTE: Exceptions thrown during VM initialization are caught in the
+         exception functions themselves.
+
 *******************************************************************************/
  
 void loader_preinit(void)
 {
 #if defined(ENABLE_THREADS)
        list_classpath_entry *lce;
+#endif
 
+       TRACESUBSYSTEMINITIALIZATION("loader_preinit");
+
+#if defined(ENABLE_THREADS)
        /* Initialize the monitor pointer for zip/jar file locking. */
 
        for (lce = list_first(list_classpath_entries); lce != NULL;
@@ -110,19 +117,15 @@ void loader_preinit(void)
        hashtable_classloader = NEW(hashtable);
        hashtable_create(hashtable_classloader, 10);
 
-       /* Load the most basic class. */
+       /* Load the most basic classes. */
 
-       if (!(class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object)))
-               vm_abort("loader_preinit: loading java/lang/Object failed");
+       assert(vm_initializing == true);
 
-#if defined(ENABLE_JAVASE)
-       if (!(class_java_lang_Cloneable =
-                 load_class_bootstrap(utf_java_lang_Cloneable)))
-               vm_abort("loader_preinit: loading java/lang/Cloneable failed");
+       class_java_lang_Object     = load_class_bootstrap(utf_java_lang_Object);
 
-       if (!(class_java_io_Serializable =
-                 load_class_bootstrap(utf_java_io_Serializable)))
-               vm_abort("loader_preinit: loading java/io/Serializable failed");
+#if defined(ENABLE_JAVASE)
+       class_java_lang_Cloneable  = load_class_bootstrap(utf_java_lang_Cloneable);
+       class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
 #endif
 }
 
@@ -131,133 +134,116 @@ void loader_preinit(void)
 
    Loads all classes required in the VM.
 
+   NOTE: Exceptions thrown during VM initialization are caught in the
+         exception functions themselves.
+
 *******************************************************************************/
  
 void loader_init(void)
 {
+       TRACESUBSYSTEMINITIALIZATION("loader_init");
+
        /* Load primitive-type wrapping classes. */
 
+       assert(vm_initializing == true);
+
 #if defined(ENABLE_JAVASE)
-       if (!(class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_Void       = load_class_bootstrap(utf_java_lang_Void);
 #endif
 
-       if (!(class_java_lang_Boolean =
-                 load_class_bootstrap(utf_java_lang_Boolean)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Character =
-                 load_class_bootstrap(utf_java_lang_Character)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Integer =
-                 load_class_bootstrap(utf_java_lang_Integer)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_Boolean    = load_class_bootstrap(utf_java_lang_Boolean);
+       class_java_lang_Byte       = load_class_bootstrap(utf_java_lang_Byte);
+       class_java_lang_Character  = load_class_bootstrap(utf_java_lang_Character);
+       class_java_lang_Short      = load_class_bootstrap(utf_java_lang_Short);
+       class_java_lang_Integer    = load_class_bootstrap(utf_java_lang_Integer);
+       class_java_lang_Long       = load_class_bootstrap(utf_java_lang_Long);
+       class_java_lang_Float      = load_class_bootstrap(utf_java_lang_Float);
+       class_java_lang_Double     = load_class_bootstrap(utf_java_lang_Double);
 
        /* Load important system classes. */
 
-       if (!(class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class)))
-               vm_abort("loader_init: loading failed");
-
-       if (!(class_java_lang_String = load_class_bootstrap(utf_java_lang_String)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_Class      = load_class_bootstrap(utf_java_lang_Class);
+       class_java_lang_String     = load_class_bootstrap(utf_java_lang_String);
 
 #if defined(ENABLE_JAVASE)
-       if (!(class_java_lang_ClassLoader =
-                 load_class_bootstrap(utf_java_lang_ClassLoader)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_ClassLoader =
+               load_class_bootstrap(utf_java_lang_ClassLoader);
 
-       if (!(class_java_lang_SecurityManager =
-                 load_class_bootstrap(utf_java_lang_SecurityManager)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_SecurityManager =
+               load_class_bootstrap(utf_java_lang_SecurityManager);
 #endif
 
-       if (!(class_java_lang_System = load_class_bootstrap(utf_java_lang_System)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_System     =
+               load_class_bootstrap(utf_new_char("java/lang/System"));
 
-       if (!(class_java_lang_Thread =
-                 load_class_bootstrap(utf_new_char("java/lang/Thread"))))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_Thread     =
+               load_class_bootstrap(utf_new_char("java/lang/Thread"));
 
 #if defined(ENABLE_JAVASE)
-       if (!(class_java_lang_ThreadGroup =
-                 load_class_bootstrap(utf_java_lang_ThreadGroup)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_ThreadGroup =
+               load_class_bootstrap(utf_java_lang_ThreadGroup);
 #endif
 
-#if defined(WITH_CLASSPATH_GNU)
-       if (!(class_java_lang_VMSystem =
-                 load_class_bootstrap(utf_new_char("java/lang/VMSystem"))))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_Throwable  = load_class_bootstrap(utf_java_lang_Throwable);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       class_java_lang_VMSystem   =
+               load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
 
-       if (!(class_java_lang_VMThread =
-                 load_class_bootstrap(utf_new_char("java/lang/VMThread"))))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_VMThread   =
+               load_class_bootstrap(utf_new_char("java/lang/VMThread"));
+
+       class_java_lang_VMThrowable =
+               load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
 #endif
 
+       /* Important system exceptions. */
 
-       /* some classes which may be used more often */
+       class_java_lang_Exception  = load_class_bootstrap(utf_java_lang_Exception);
 
-#if defined(ENABLE_JAVASE)
-       if (!(class_java_lang_StackTraceElement =
-                 load_class_bootstrap(utf_java_lang_StackTraceElement)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_ClassNotFoundException =
+               load_class_bootstrap(utf_java_lang_ClassNotFoundException);
 
-       if (!(class_java_lang_reflect_Constructor =
-                 load_class_bootstrap(utf_java_lang_reflect_Constructor)))
-               vm_abort("loader_init: loading failed");
+       class_java_lang_RuntimeException =
+               load_class_bootstrap(utf_java_lang_RuntimeException);
 
-       if (!(class_java_lang_reflect_Field =
-                 load_class_bootstrap(utf_java_lang_reflect_Field)))
-               vm_abort("loader_init: loading failed");
+       /* Some classes which may be used often. */
 
-       if (!(class_java_lang_reflect_Method =
-                 load_class_bootstrap(utf_java_lang_reflect_Method)))
-               vm_abort("loader_init: loading failed");
+#if defined(ENABLE_JAVASE)
+       class_java_lang_StackTraceElement      = load_class_bootstrap(utf_java_lang_StackTraceElement);
+
+       class_java_lang_reflect_Constructor    = load_class_bootstrap(utf_java_lang_reflect_Constructor);
+       class_java_lang_reflect_Field          = load_class_bootstrap(utf_java_lang_reflect_Field);
+       class_java_lang_reflect_Method         = load_class_bootstrap(utf_java_lang_reflect_Method);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       class_java_lang_reflect_VMConstructor  = load_class_bootstrap(utf_java_lang_reflect_VMConstructor);
+       class_java_lang_reflect_VMField        = load_class_bootstrap(utf_java_lang_reflect_VMField);
+       class_java_lang_reflect_VMMethod       = load_class_bootstrap(utf_java_lang_reflect_VMMethod);
+# endif
 
-       if (!(class_java_security_PrivilegedAction =
-                 load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"))))
-               vm_abort("loader_init: loading failed");
+       class_java_security_PrivilegedAction   = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
 
-       if (!(class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector)))
-               vm_abort("loader_init: loading failed");
+       class_java_util_HashMap                = load_class_bootstrap(utf_new_char("java/util/HashMap"));
+       class_java_util_Vector                 = load_class_bootstrap(utf_java_util_Vector);
 
-# if defined(WITH_CLASSPATH_SUN)
-       if (!(class_sun_reflect_MagicAccessorImpl =
-                 load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"))))
-               vm_abort("loader_init: loading failed");
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       class_sun_reflect_MagicAccessorImpl =
+               load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
 # endif
 
-       if (!(arrayclass_java_lang_Object =
-                 load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"))))
-               vm_abort("loader_init: loading failed");
+       arrayclass_java_lang_Object =
+               load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
 
 # if defined(ENABLE_ANNOTATIONS)
        /* needed by annotation support */
-       if (!(class_sun_reflect_ConstantPool = 
-                 load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"))))
-               vm_abort("loader_init: loading failed");
+       class_sun_reflect_ConstantPool =
+               load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
 
-#  if defined(WITH_CLASSPATH_GNU)
+#  if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
        /* needed by GNU Classpaths annotation support */
-       if (!(class_sun_reflect_annotation_AnnotationParser = 
-                 load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"))))
-               vm_abort("loader_init: loading failed");
+       class_sun_reflect_annotation_AnnotationParser =
+               load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
 #  endif
 # endif
 #endif
@@ -272,7 +258,7 @@ void loader_init(void)
 
 *******************************************************************************/
 
-classloader *loader_hashtable_classloader_add(java_handle_t *cl)
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
 {
        hashtable_classloader_entry *cle;
        u4   key;
@@ -288,12 +274,7 @@ classloader *loader_hashtable_classloader_add(java_handle_t *cl)
        /* key for entry is the hashcode of the classloader;
           aligned to 16-byte boundaries */
 
-#if defined(ENABLE_GC_CACAO)
-       key  = heap_get_hashcode(LLNI_DIRECT(cl)) >> 4;
-#else
-       key  = ((u4) (ptrint) cl) >> 4;
-#endif
-
+       key  = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
        slot = key & (hashtable_classloader->size - 1);
        cle  = hashtable_classloader->ptr[slot];
 
@@ -325,6 +306,14 @@ classloader *loader_hashtable_classloader_add(java_handle_t *cl)
 
                LLNI_CRITICAL_END;
 
+/*#define LOADER_DEBUG_CLASSLOADER*/
+#ifdef LOADER_DEBUG_CLASSLOADER
+               printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
+               class_print(LLNI_vftbl_direct(cl)->class);
+               printf("\n");
+               fflush(stdout);
+#endif
+
                /* insert entry into hashtable */
 
                cle->hashlink = hashtable_classloader->ptr[slot];
@@ -338,7 +327,11 @@ classloader *loader_hashtable_classloader_add(java_handle_t *cl)
 
        LOCK_MONITOR_EXIT(hashtable_classloader->header);
 
+#if defined(ENABLE_HANDLES)
        return cle;
+#else
+       return cl;
+#endif
 }
 
 
@@ -348,7 +341,7 @@ classloader *loader_hashtable_classloader_add(java_handle_t *cl)
 
 *******************************************************************************/
 
-classloader *loader_hashtable_classloader_find(java_handle_t *cl)
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
 {
        hashtable_classloader_entry *cle;
        u4   key;
@@ -362,12 +355,7 @@ classloader *loader_hashtable_classloader_find(java_handle_t *cl)
        /* key for entry is the hashcode of the classloader;
           aligned to 16-byte boundaries */
 
-#if defined(ENABLE_GC_CACAO)
-       key  = heap_get_hashcode(LLNI_DIRECT(cl)) >> 4;
-#else
-       key  = ((u4) (ptrint) cl) >> 4;
-#endif
-
+       key  = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
        slot = key & (hashtable_classloader->size - 1);
        cle  = hashtable_classloader->ptr[slot];
 
@@ -380,9 +368,22 @@ classloader *loader_hashtable_classloader_find(java_handle_t *cl)
                cle = cle->hashlink;
        }
 
+#ifdef LOADER_DEBUG_CLASSLOADER
+       if (cle == NULL) {
+               printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
+               class_print(LLNI_vftbl_direct(cl)->class);
+               printf("\n");
+               fflush(stdout);
+       }
+#endif
+
        LLNI_CRITICAL_END;
 
+#if defined(ENABLE_HANDLES)
        return cle;
+#else
+       return cl;
+#endif
 }
 
 
@@ -544,7 +545,7 @@ static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
        u1 *cptags;
        voidptr *cpinfos;
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* number of entries in the constant_pool table plus one */
        if (!suck_check_classbuffer_size(cb, 2))
@@ -936,7 +937,7 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
 
        /* get classinfo */
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* check remaining bytecode */
 
@@ -986,7 +987,7 @@ classinfo *load_class_from_sysloader(utf *name)
 {
        methodinfo    *m;
        java_handle_t *clo;
-       classloader   *cl;
+       classloader_t *cl;
        classinfo     *c;
 
        assert(class_java_lang_Object);
@@ -1029,7 +1030,7 @@ classinfo *load_class_from_sysloader(utf *name)
 
 *******************************************************************************/
 
-classinfo *load_class_from_classloader(utf *name, classloader *cl)
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
 {
        java_handle_t *o;
        classinfo     *c;
@@ -1126,18 +1127,20 @@ classinfo *load_class_from_classloader(utf *name, classloader *cl)
                                return c;
                        }
                }
-               
-#if defined(WITH_CLASSPATH_SUN)
+
+               LLNI_class_get(cl, c);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
                /* OpenJDK uses this internal function because it's
                   synchronized. */
 
-               lc = class_resolveclassmethod(cl->object->vftbl->class,
+               lc = class_resolveclassmethod(c,
                                                                          utf_loadClassInternal,
                                                                          utf_java_lang_String__java_lang_Class,
                                                                          NULL,
                                                                          true);
 #else
-               lc = class_resolveclassmethod(cl->object->vftbl->class,
+               lc = class_resolveclassmethod(c,
                                                                          utf_loadClass,
                                                                          utf_java_lang_String__java_lang_Class,
                                                                          NULL,
@@ -1153,11 +1156,7 @@ classinfo *load_class_from_classloader(utf *name, classloader *cl)
 
                RT_TIMING_GET_TIME(time_prepare);
 
-#if defined(ENABLE_HANDLES)
                o = vm_call_method(lc, (java_handle_t *) cl, string);
-#else
-               o = vm_call_method(lc, cl->object, string);
-#endif
 
                RT_TIMING_GET_TIME(time_java);
 
@@ -1293,13 +1292,7 @@ classinfo *load_class_bootstrap(utf *name)
        cb = suck_start(c);
 
        if (cb == NULL) {
-               /* this normally means, the classpath was not set properly */
-
-               if (name == utf_java_lang_Object)
-                       vm_abort("java/lang/NoClassDefFoundError: java/lang/Object");
-
                exceptions_throw_classnotfoundexception(name);
-
                return NULL;
        }
 
@@ -1311,22 +1304,27 @@ classinfo *load_class_bootstrap(utf *name)
 
        RT_TIMING_GET_TIME(time_load);
        
-       if (!r) {
+       if (r == NULL) {
                /* the class could not be loaded, free the classinfo struct */
 
                class_free(c);
-
-       else {
+       }
+       else {
                /* Store this class in the loaded class cache this step also
-               checks the loading constraints. If the class has been loaded
-               before, the earlier loaded class is returned. */
+                  checks the loading constraints. If the class has been
+                  loaded before, the earlier loaded class is returned. */
 
                classinfo *res = classcache_store(NULL, c, true);
 
-               if (!res) {
+               if (res == NULL) {
                        /* exception */
                        class_free(c);
                }
+               else {
+                       /* Add the package name to the boot packages. */
+
+                       Package_add(c->packagename);
+               }
 
                r = res;
        }
@@ -1377,9 +1375,15 @@ classinfo *load_class_bootstrap(utf *name)
 
 static bool load_class_from_classbuffer_intern(classbuffer *cb)
 {
-       classinfo *c;
-       utf *name;
-       utf *supername;
+       classinfo          *c;
+       classinfo          *tc;
+       utf                *name;
+       utf                *supername;
+       utf               **interfacesnames;
+       utf                *u;
+       constant_classref  *cr;
+       int16_t             index;
+
        u4 i,j;
        u4 ma, mi;
        descriptor_pool *descpool;
@@ -1398,7 +1402,7 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
 
        /* Get the classbuffer's class. */
 
-       c = cb->class;
+       c = cb->clazz;
 
        if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
                return false;
@@ -1477,11 +1481,13 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
        if (!suck_check_classbuffer_size(cb, 2 + 2))
                return false;
 
-       /* this class */
+       /* This class. */
+
+       index = suck_u2(cb);
 
-       i = suck_u2(cb);
+       name = (utf *) class_getconstant(c, index, CONSTANT_Class);
 
-       if (!(name = (utf *) class_getconstant(c, i, CONSTANT_Class)))
+       if (name == NULL)
                return false;
 
        if (c->name == utf_not_named_yet) {
@@ -1494,12 +1500,26 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
                return false;
        }
 
-       /* retrieve superclass */
+       /* Retrieve superclass. */
+
+       c->super = NULL;
 
-       c->super.any = NULL;
+       index = suck_u2(cb);
 
-       if ((i = suck_u2(cb))) {
-               if (!(supername = (utf *) class_getconstant(c, i, CONSTANT_Class)))
+       if (index == 0) {
+               supername = NULL;
+
+               /* This is only allowed for java.lang.Object. */
+
+               if (c->name != utf_java_lang_Object) {
+                       exceptions_throw_classformaterror(c, "Bad superclass index");
+                       return false;
+               }
+       }
+       else {
+               supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+               if (supername == NULL)
                        return false;
 
                /* java.lang.Object may not have a super class. */
@@ -1509,25 +1529,22 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
                        return false;
                }
 
-               /* Interfaces must have java.lang.Object as super class. */
+               /* Detect circularity. */
 
-               if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
-                       exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
+               if (supername == c->name) {
+                       exceptions_throw_classcircularityerror(c);
                        return false;
                }
-       }
-       else {
-               supername = NULL;
 
-               /* This is only allowed for java.lang.Object. */
+               /* Interfaces must have java.lang.Object as super class. */
 
-               if (c->name != utf_java_lang_Object) {
-                       exceptions_throw_classformaterror(c, "Bad superclass index");
+               if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
+                       exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
                        return false;
                }
        }
 
-       /* retrieve interfaces */
+       /* Parse the super interfaces. */
 
        if (!suck_check_classbuffer_size(cb, 2))
                return false;
@@ -1537,17 +1554,26 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
        if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
                return false;
 
-       c->interfaces = MNEW(classref_or_classinfo, c->interfacescount);
+       c->interfaces = MNEW(classinfo*, c->interfacescount);
+
+       /* Get the names of the super interfaces. */
+
+       interfacesnames = DMNEW(utf*, c->interfacescount);
 
        for (i = 0; i < c->interfacescount; i++) {
-               /* the classrefs are created later */
-               if (!(c->interfaces[i].any = (utf *) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+               index = suck_u2(cb);
+
+               u = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+               if (u == NULL)
                        return false;
+
+               interfacesnames[i] = u;
        }
 
        RT_TIMING_GET_TIME(time_setup);
 
-       /* load fields */
+       /* Parse fields. */
 
        if (!suck_check_classbuffer_size(cb, 2))
                return false;
@@ -1564,7 +1590,7 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
 
        RT_TIMING_GET_TIME(time_fields);
 
-       /* load methods */
+       /* Parse methods. */
 
        if (!suck_check_classbuffer_size(cb, 2))
                return false;
@@ -1605,6 +1631,7 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
        RT_TIMING_GET_TIME(time_descs);
 
        /* put the classrefs in the constant pool */
+
        for (i = 0; i < c->cpcount; i++) {
                if (c->cptags[i] == CONSTANT_Class) {
                        utf *name = (utf *) c->cpinfos[i];
@@ -1612,27 +1639,80 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
                }
        }
 
-       /* set the super class reference */
+       /* Resolve the super class. */
+
+       if (supername != NULL) {
+               cr = descriptor_pool_lookup_classref(descpool, supername);
 
-       if (supername) {
-               c->super.ref = descriptor_pool_lookup_classref(descpool, supername);
-               if (!c->super.ref)
+               if (cr == NULL)
                        return false;
+
+               /* XXX This should be done better. */
+               tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+               if (tc == NULL) {
+                       resolve_handle_pending_exception(true);
+                       return false;
+               }
+
+               /* Interfaces are not allowed as super classes. */
+
+               if (tc->flags & ACC_INTERFACE) {
+                       exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
+                       return false;
+               }
+
+               /* Don't allow extending final classes */
+
+               if (tc->flags & ACC_FINAL) {
+                       exceptions_throw_verifyerror(NULL,
+                                                                                "Cannot inherit from final class");
+                       return false;
+               }
+
+               /* Store the super class. */
+
+               c->super = tc;
        }
 
-       /* set the super interfaces references */
+       /* Resolve the super interfaces. */
 
        for (i = 0; i < c->interfacescount; i++) {
-               c->interfaces[i].ref =
-                       descriptor_pool_lookup_classref(descpool,
-                                                                                       (utf *) c->interfaces[i].any);
-               if (!c->interfaces[i].ref)
+               u  = interfacesnames[i];
+               cr = descriptor_pool_lookup_classref(descpool, u);
+
+               if (cr == NULL)
+                       return false;
+
+               /* XXX This should be done better. */
+               tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+               if (tc == NULL) {
+                       resolve_handle_pending_exception(true);
+                       return false;
+               }
+
+               /* Detect circularity. */
+
+               if (tc == c) {
+                       exceptions_throw_classcircularityerror(c);
                        return false;
+               }
+
+               if (!(tc->flags & ACC_INTERFACE)) {
+                       exceptions_throw_incompatibleclasschangeerror(tc,
+                                                                                                                 "Implementing class");
+                       return false;
+               }
+
+               /* Store the super interface. */
+
+               c->interfaces[i] = tc;
        }
 
        RT_TIMING_GET_TIME(time_setrefs);
 
-       /* parse field descriptors */
+       /* Parse the field descriptors. */
 
        for (i = 0; i < c->fieldscount; i++) {
                c->fields[i].parseddesc =
@@ -1650,7 +1730,7 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
                methodinfo *m = &c->methods[i];
                m->parseddesc =
                        descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
-                                                                                                       m->flags, class_get_self_classref(m->class));
+                                                                                                       m->flags, class_get_self_classref(m->clazz));
                if (!m->parseddesc)
                        return false;
 
@@ -1867,12 +1947,12 @@ static bool load_class_from_classbuffer_intern(classbuffer *cb)
 classinfo *load_class_from_classbuffer(classbuffer *cb)
 {
        classinfo *c;
-       int32_t    dumpsize;
        bool       result;
+       int32_t    dumpmarker;
 
        /* Get the classbuffer's class. */
 
-       c = cb->class;
+       c = cb->clazz;
 
        /* Check if the class is already loaded. */
 
@@ -1891,7 +1971,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        /* Mark start of dump memory area. */
 
-       dumpsize = dump_size();
+       DMARKER;
 
        /* Class is currently loading. */
 
@@ -1903,7 +1983,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        /* Release dump area. */
 
-       dump_release(dumpsize);
+       DRELEASE;
 
        /* An error occurred. */
 
@@ -1953,7 +2033,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
 *******************************************************************************/
 
-classinfo *load_newly_created_array(classinfo *c, classloader *loader)
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
 {
        classinfo         *comp = NULL;
        methodinfo        *clone;
@@ -2036,31 +2116,33 @@ classinfo *load_newly_created_array(classinfo *c, classloader *loader)
        assert(class_java_io_Serializable);
 #endif
 
-       /* setup the array class */
+       /* Setup the array class. */
 
-       c->super.cls = class_java_lang_Object;
+       c->super = class_java_lang_Object;
 
 #if defined(ENABLE_JAVASE)
 
-       c->interfacescount   = 2;
-    c->interfaces        = MNEW(classref_or_classinfo, 2);
-       c->interfaces[0].cls = class_java_lang_Cloneable;
-       c->interfaces[1].cls = class_java_io_Serializable;
+       c->interfacescount = 2;
+    c->interfaces      = MNEW(classinfo*, 2);
+       c->interfaces[0]   = class_java_lang_Cloneable;
+       c->interfaces[1]   = class_java_io_Serializable;
 
 #elif defined(ENABLE_JAVAME_CLDC1_1)
 
-       c->interfacescount   = 0;
-       c->interfaces        = NULL;
+       c->interfacescount = 0;
+       c->interfaces      = NULL;
 
 #else
 # error unknow Java configuration
 #endif
 
        c->methodscount = 1;
-       c->methods = MNEW(methodinfo, c->methodscount);
+       c->methods      = MNEW(methodinfo, c->methodscount);
+
        MZERO(c->methods, methodinfo, c->methodscount);
 
        classrefs = MNEW(constant_classref, 2);
+
        CLASSREF_INIT(classrefs[0], c, c->name);
        CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
 
@@ -2093,7 +2175,7 @@ classinfo *load_newly_created_array(classinfo *c, classloader *loader)
        clone->name       = utf_clone;
        clone->descriptor = utf_void__java_lang_Object;
        clone->parseddesc = clonedesc;
-       clone->class      = c;
+       clone->clazz      = c;
 
        /* parse the descriptor to get the register allocation */