* src/vm/initialize.c: Moved to C++.
[cacao.git] / src / vm / class.c
index 215d60d0761988257b9534cc71c3ed1bd8cdf66d..f5a6ffd1c031c5ee9940aa3b7f28a78a08cdcbdf 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/class.c - class related functions
 
-   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
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Reinhard Grafl
-
-   Changes: Mark Probst
-            Andreas Krall
-            Christian Thalinger
+*/
 
-   $Id: class.c 3940 2005-12-11 01:06:16Z twisti $
 
-*/
+#include "config.h"
 
 #include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
-#include "config.h"
 #include "vm/types.h"
 
+#include "arch.h"
+
 #include "mm/memory.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 "native/llni.h"
+
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
 
 #include "toolbox/logging.h"
+
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
 #include "vm/class.h"
 #include "vm/classcache.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
 #include "vm/options.h"
-#include "vm/resolve.h"
-#include "vm/statistics.h"
-#include "vm/stringlocal.h"
-#include "vm/utf8.h"
-
-
-/******************************************************************************/
-/* DEBUG HELPERS                                                              */
-/******************************************************************************/
-
-#ifndef NDEBUG
-#define CLASS_DEBUG
-#endif
+#include "vm/resolve.hpp"
 
-#ifdef CLASS_DEBUG
-#define CLASS_ASSERT(cond)  assert(cond)
-#else
-#define CLASS_ASSERT(cond)
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
 #endif
 
+#include "vm/suck.hpp"
+#include "vm/utf8.h"
 
-/* global variables ***********************************************************/
-
-list unlinkedclasses;                   /* this is only used for eager class  */
-                                        /* loading                            */
-
-
-/* frequently used classes ****************************************************/
-
-/* important system classes */
-
-classinfo *class_java_lang_Object = NULL;
-classinfo *class_java_lang_Class = NULL;
-classinfo *class_java_lang_ClassLoader = NULL;
-classinfo *class_java_lang_Cloneable = NULL;
-classinfo *class_java_lang_SecurityManager = NULL;
-classinfo *class_java_lang_String = NULL;
-classinfo *class_java_lang_System = NULL;
-classinfo *class_java_lang_Thread = NULL;
-classinfo *class_java_lang_ThreadGroup = NULL;
-classinfo *class_java_lang_VMThread = NULL;
-classinfo *class_java_io_Serializable = NULL;
-
-
-/* system exception classes required in cacao */
-
-classinfo *class_java_lang_Throwable = NULL;
-classinfo *class_java_lang_VMThrowable = NULL;
-classinfo *class_java_lang_Error = NULL;
-classinfo *class_java_lang_NoClassDefFoundError = NULL;
-classinfo *class_java_lang_LinkageError = NULL;
-classinfo *class_java_lang_NoSuchMethodError = NULL;
-classinfo *class_java_lang_OutOfMemoryError = NULL;
-
-classinfo *class_java_lang_Exception = NULL;
-classinfo *class_java_lang_ClassNotFoundException = NULL;
-classinfo *class_java_lang_IllegalArgumentException = NULL;
-classinfo *class_java_lang_IllegalMonitorStateException = NULL;
-
-classinfo *class_java_lang_Void = NULL;
-classinfo *class_java_lang_Boolean = NULL;
-classinfo *class_java_lang_Byte = NULL;
-classinfo *class_java_lang_Character = NULL;
-classinfo *class_java_lang_Short = NULL;
-classinfo *class_java_lang_Integer = NULL;
-classinfo *class_java_lang_Long = NULL;
-classinfo *class_java_lang_Float = NULL;
-classinfo *class_java_lang_Double = NULL;
-
-
-/* some runtime exception */
-
-classinfo *class_java_lang_NullPointerException = NULL;
-
-
-/* some classes which may be used more often */
-
-classinfo *class_java_lang_StackTraceElement = NULL;
-classinfo *class_java_lang_reflect_Constructor = NULL;
-classinfo *class_java_lang_reflect_Field = NULL;
-classinfo *class_java_lang_reflect_Method = NULL;
-classinfo *class_java_security_PrivilegedAction = NULL;
-classinfo *class_java_util_Vector = NULL;
-
-classinfo *arrayclass_java_lang_Object = NULL;
-
+#include "vm/jit/asmpart.h"
 
-/* pseudo classes for the typechecker */
 
-classinfo *pseudo_class_Arraystub = NULL;
-classinfo *pseudo_class_Null = NULL;
-classinfo *pseudo_class_New = NULL;
+/* class_set_packagename *******************************************************
 
+   Derive the package name from the class name and store it in the
+   struct.
 
-/* class_set_packagename *******************************************************
+   An internal package name consists of the package name plus the
+   trailing '/', e.g. "java/lang/".
 
-   Derive the package name from the class name and store it in the struct.
+   For classes in the unnamed package, the package name is set to
+   NULL.
 
 *******************************************************************************/
 
 void class_set_packagename(classinfo *c)
 {
-       char *p = UTF_END(c->name) - 1;
-       char *start = c->name->text;
+       char *p;
+       char *start;
 
-       /* set the package name */
-       /* classes in the unnamed package keep packagename == NULL */
+       p     = UTF_END(c->name) - 1;
+       start = c->name->text;
 
        if (c->name->text[0] == '[') {
-               /* set packagename of arrays to the element's package */
+               /* Set packagename of arrays to the element's package. */
 
                for (; *start == '['; start++);
 
-               /* skip the 'L' in arrays of references */
+               /* Skip the 'L' in arrays of references. */
+
                if (*start == 'L')
                        start++;
+       }
 
-               for (; (p > start) && (*p != '/'); --p);
+       /* Search for last '/'. */
 
-               c->packagename = utf_new(start, p - start);
+       for (; (p > start) && (*p != '/'); --p);
 
-       } else {
-               for (; (p > start) && (*p != '/'); --p);
+       /* If we found a '/' we set the package name plus the trailing
+          '/'.  Otherwise we set the packagename to NULL. */
 
-               c->packagename = utf_new(start, p - start);
-       }
+       if (p > start)
+               c->packagename = utf_new(start, p - start + 1);
+       else
+               c->packagename = NULL;
 }
 
 
@@ -202,37 +127,57 @@ classinfo *class_create_classinfo(utf *classname)
 {
        classinfo *c;
 
-#if defined(STATISTICS)
+#if defined(ENABLE_STATISTICS)
        if (opt_stat)
-               count_class_infos += sizeof(classinfo);
+               size_classinfo += sizeof(classinfo);
 #endif
 
        /* we use a safe name for temporarily unnamed classes */
-       if (!classname)
+
+       if (classname == NULL)
                classname = utf_not_named_yet;
 
+#if !defined(NDEBUG)
        if (initverbose)
                log_message_utf("Creating class: ", classname);
+#endif
 
+#if !defined(ENABLE_GC_BOEHM)
+       c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+       /*c = NEW(classinfo);
+       MZERO(c, classinfo, 1);*/
+#else
+       c = GCNEW_UNCOLLECTABLE(classinfo, 1);
        /* GCNEW_UNCOLLECTABLE clears the allocated memory */
+#endif
 
-       c = GCNEW_UNCOLLECTABLE(classinfo, 1);
-       /*c=NEW(classinfo);*/
        c->name = classname;
 
-       /* set the header.vftbl of all loaded classes to the one of
-       java.lang.Class, so Java code can use a class as object */
+       /* Set the header.vftbl of all loaded classes to the one of
+       java.lang.Class, so Java code can use a class as object. */
 
-       if (class_java_lang_Class)
-               if (class_java_lang_Class->vftbl)
+       if (class_java_lang_Class != NULL)
+               if (class_java_lang_Class->vftbl != NULL)
                        c->object.header.vftbl = class_java_lang_Class->vftbl;
-       
+
+#if defined(ENABLE_JAVASE)
+       /* check if the class is a reference class and flag it */
+
+       if (classname == utf_java_lang_ref_SoftReference) {
+               c->flags |= ACC_CLASS_REFERENCE_SOFT;
+       }
+       else if (classname == utf_java_lang_ref_WeakReference) {
+               c->flags |= ACC_CLASS_REFERENCE_WEAK;
+       }
+       else if (classname == utf_java_lang_ref_PhantomReference) {
+               c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
+       }
+#endif
+
        if (classname != utf_not_named_yet)
                class_set_packagename(c);
 
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-       initObjectLock(&c->object.header);
-#endif
+       Lockword_init(&(c->object.header.lockword));
 
        return c;
 }
@@ -273,6 +218,391 @@ void class_postset_header_vftbl(void)
        }
 }
 
+/* class_define ****************************************************************
+
+   Calls the loader and defines a class in the VM.
+
+*******************************************************************************/
+
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
+{
+       classinfo   *c;
+       classinfo   *r;
+       classbuffer *cb;
+
+       if (name != NULL) {
+               /* check if this class has already been defined */
+
+               c = classcache_lookup_defined_or_initiated(cl, name);
+
+               if (c != NULL) {
+                       exceptions_throw_linkageerror("duplicate class definition: ", c);
+                       return NULL;
+               }
+       } 
+
+       /* create a new classinfo struct */
+
+       c = class_create_classinfo(name);
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getloadingtime)
+               loadingtime_start();
+#endif
+
+       /* build a classbuffer with the given data */
+
+       cb = NEW(classbuffer);
+
+       cb->clazz = c;
+       cb->size  = length;
+       cb->data  = data;
+       cb->pos   = cb->data;
+
+       /* preset the defining classloader */
+
+       c->classloader = cl;
+
+       /* load the class from this buffer */
+
+       r = load_class_from_classbuffer(cb);
+
+       /* free memory */
+
+       FREE(cb, classbuffer);
+
+#if defined(ENABLE_STATISTICS)
+       /* measure time */
+
+       if (opt_getloadingtime)
+               loadingtime_stop();
+#endif
+
+       if (r == NULL) {
+               /* If return value is NULL, we had a problem and the class is
+                  not loaded.  Now free the allocated memory, otherwise we
+                  could run into a DOS. */
+
+               class_free(c);
+
+               return NULL;
+       }
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       /* Store the protection domain. */
+
+       c->protectiondomain = pd;
+# endif
+#endif
+
+       /* Store the newly defined class in the class cache. This call
+          also checks whether a class of the same name has already been
+          defined by the same defining loader, and if so, replaces the
+          newly created class by the one defined earlier. */
+
+       /* Important: The classinfo given to classcache_store must be
+                     fully prepared because another thread may return
+                     this pointer after the lookup at to top of this
+                     function directly after the class cache lock has
+                     been released. */
+
+       c = classcache_store(cl, c, true);
+
+       return c;
+}
+
+
+/* class_load_attribute_sourcefile *********************************************
+
+   SourceFile_attribute {
+       u2 attribute_name_index;
+       u4 attribute_length;
+          u2 sourcefile_index;
+   }
+
+*******************************************************************************/
+
+static bool class_load_attribute_sourcefile(classbuffer *cb)
+{
+       classinfo *c;
+       u4         attribute_length;
+       u2         sourcefile_index;
+       utf       *sourcefile;
+
+       /* get classinfo */
+
+       c = cb->clazz;
+
+       /* check buffer size */
+
+       if (!suck_check_classbuffer_size(cb, 4 + 2))
+               return false;
+
+       /* check attribute length */
+
+       attribute_length = suck_u4(cb);
+
+       if (attribute_length != 2) {
+               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+               return false;
+       }
+
+       /* there can be no more than one SourceFile attribute */
+
+       if (c->sourcefile != NULL) {
+               exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
+               return false;
+       }
+
+       /* get sourcefile */
+
+       sourcefile_index = suck_u2(cb);
+       sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
+
+       if (sourcefile == NULL)
+               return false;
+
+       /* store sourcefile */
+
+       c->sourcefile = sourcefile;
+
+       return true;
+}
+
+
+/* class_load_attribute_enclosingmethod ****************************************
+
+   EnclosingMethod_attribute {
+       u2 attribute_name_index;
+       u4 attribute_length;
+          u2 class_index;
+          u2 method_index;
+   }
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+static bool class_load_attribute_enclosingmethod(classbuffer *cb)
+{
+       classinfo             *c;
+       u4                     attribute_length;
+       u2                     class_index;
+       u2                     method_index;
+       classref_or_classinfo  cr;
+       constant_nameandtype  *cn;
+
+       /* get classinfo */
+
+       c = cb->clazz;
+
+       /* check buffer size */
+
+       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+               return false;
+
+       /* check attribute length */
+
+       attribute_length = suck_u4(cb);
+
+       if (attribute_length != 4) {
+               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+               return false;
+       }
+
+       /* there can be no more than one EnclosingMethod attribute */
+
+       if (c->enclosingmethod != NULL) {
+               exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
+               return false;
+       }
+
+       /* get class index */
+
+       class_index = suck_u2(cb);
+       cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
+
+       /* get method index */
+
+       method_index = suck_u2(cb);
+       cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
+
+       /* store info in classinfo */
+
+       c->enclosingclass.any = cr.any;
+       c->enclosingmethod    = cn;
+
+       return true;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/* class_load_attributes *******************************************************
+
+   Read attributes from ClassFile.
+
+   attribute_info {
+       u2 attribute_name_index;
+       u4 attribute_length;
+       u1 info[attribute_length];
+   }
+
+   InnerClasses_attribute {
+       u2 attribute_name_index;
+       u4 attribute_length;
+   }
+
+*******************************************************************************/
+
+bool class_load_attributes(classbuffer *cb)
+{
+       classinfo             *c;
+       uint16_t               attributes_count;
+       uint16_t               attribute_name_index;
+       utf                   *attribute_name;
+       innerclassinfo        *info;
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *name;
+       uint16_t               flags;
+       int                    i, j;
+
+       c = cb->clazz;
+
+       /* get attributes count */
+
+       if (!suck_check_classbuffer_size(cb, 2))
+               return false;
+
+       attributes_count = suck_u2(cb);
+
+       for (i = 0; i < attributes_count; i++) {
+               /* get attribute name */
+
+               if (!suck_check_classbuffer_size(cb, 2))
+                       return false;
+
+               attribute_name_index = suck_u2(cb);
+               attribute_name =
+                       class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+
+               if (attribute_name == NULL)
+                       return false;
+
+               if (attribute_name == utf_InnerClasses) {
+                       /* InnerClasses */
+
+                       if (c->innerclass != NULL) {
+                               exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
+                               return false;
+                       }
+                               
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
+                               return false;
+
+                       /* skip attribute length */
+                       suck_u4(cb);
+
+                       /* number of records */
+                       c->innerclasscount = suck_u2(cb);
+
+                       if (!suck_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++) {
+                               /* The innerclass structure contains a class with an encoded
+                                  name, its defining scope, its simple name and a bitmask of
+                                  the access flags. */
+                                                               
+                               info = c->innerclass + j;
+
+                               inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               name      = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+                               flags     = suck_u2(cb);
+
+                               /* If the current inner-class is the currently loaded
+                                  class check for some special flags. */
+
+                               if (inner.ref->name == c->name) {
+                                       /* If an inner-class is not a member, its
+                                          outer-class is NULL. */
+
+                                       if (outer.ref != NULL) {
+                                               c->flags |= ACC_CLASS_MEMBER;
+
+                                               /* A member class doesn't have an
+                                                  EnclosingMethod attribute, so set the
+                                                  enclosing-class to be the same as the
+                                                  declaring-class. */
+
+                                               c->declaringclass = outer;
+                                               c->enclosingclass = outer;
+                                       }
+
+                                       /* If an inner-class is anonymous, its name is
+                                          NULL. */
+
+                                       if (name == NULL)
+                                               c->flags |= ACC_CLASS_ANONYMOUS;
+                               }
+
+                               info->inner_class = inner;
+                               info->outer_class = outer;
+                               info->name        = name;
+                               info->flags       = flags;
+                       }
+               }
+               else if (attribute_name == utf_SourceFile) {
+                       /* SourceFile */
+
+                       if (!class_load_attribute_sourcefile(cb))
+                               return false;
+               }
+#if defined(ENABLE_JAVASE)
+               else if (attribute_name == utf_EnclosingMethod) {
+                       /* EnclosingMethod */
+
+                       if (!class_load_attribute_enclosingmethod(cb))
+                               return false;
+               }
+               else if (attribute_name == utf_Signature) {
+                       /* Signature */
+
+                       if (!loader_load_attribute_signature(cb, &(c->signature)))
+                               return false;
+               }
+#endif
+
+#if defined(ENABLE_ANNOTATIONS)
+               else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+                       /* RuntimeVisibleAnnotations */
+                       if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+                               return false;
+               }
+               else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+                       /* RuntimeInvisibleAnnotations */
+                       if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
+                               return false;
+               }
+#endif
+
+               else {
+                       /* unknown attribute */
+
+                       if (!loader_skip_attribute_body(cb))
+                               return false;
+               }
+       }
+
+       return true;
+}
+
 
 /* class_freepool **************************************************************
 
@@ -284,7 +614,7 @@ static void class_freecpool(classinfo *c)
 {
        u4 idx;
        u4 tag;
-       voidptr info;
+       void* info;
        
        if (c->cptags && c->cpinfos) {
                for (idx = 0; idx < c->cpcount; idx++) {
@@ -322,7 +652,7 @@ static void class_freecpool(classinfo *c)
                MFREE(c->cptags, u1, c->cpcount);
 
        if (c->cpinfos)
-               MFREE(c->cpinfos, voidptr, c->cpcount);
+               MFREE(c->cpinfos, void*, c->cpcount);
 }
 
 
@@ -334,13 +664,13 @@ static void class_freecpool(classinfo *c)
 
 *******************************************************************************/
 
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
+void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* check index and type of constantpool entry */
        /* (pos == 0 is caught by type comparison) */
 
-       if (pos >= c->cpcount || c->cptags[pos] != ctype) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+       if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
                return NULL;
        }
 
@@ -354,21 +684,24 @@ voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
        
 *******************************************************************************/
 
-voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
 {
        /* invalid position in constantpool */
+
        if (pos >= c->cpcount) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
                return NULL;
        }
 
        /* constantpool entry of type 0 */      
-       if (!c->cptags[pos])
+
+       if (c->cptags[pos] == 0)
                return NULL;
 
        /* check type of constantpool entry */
+
        if (c->cptags[pos] != ctype) {
-               *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
                return NULL;
        }
                
@@ -386,16 +719,16 @@ void class_free(classinfo *c)
 {
        s4 i;
        vftbl_t *v;
-               
+
        class_freecpool(c);
 
-       if (c->interfaces)
+       if (c->interfaces != NULL)
                MFREE(c->interfaces, classinfo*, c->interfacescount);
 
        if (c->fields) {
                for (i = 0; i < c->fieldscount; i++)
                        field_free(&(c->fields[i]));
-/*     MFREE(c->fields, fieldinfo, c->fieldscount); */
+               MFREE(c->fields, fieldinfo, c->fieldscount);
        }
        
        if (c->methods) {
@@ -440,8 +773,8 @@ void class_free(classinfo *c)
 
 *******************************************************************************/
 
-static classinfo *get_array_class(utf *name,java_objectheader *initloader,
-                                                                                       java_objectheader *defloader,bool link)
+static classinfo *get_array_class(utf *name,classloader_t *initloader,
+                                                                                       classloader_t *defloader,bool link)
 {
        classinfo *c;
        
@@ -458,15 +791,15 @@ static classinfo *get_array_class(utf *name,java_objectheader *initloader,
                        return NULL;
        }
 
-       CLASS_ASSERT(c);
-       CLASS_ASSERT(c->state & CLASS_LOADED);
-       CLASS_ASSERT(c->classloader == defloader);
+       assert(c);
+       assert(c->state & CLASS_LOADED);
+       assert(c->classloader == defloader);
 
        if (link && !(c->state & CLASS_LINKED))
                if (!link_class(c))
                        return NULL;
 
-       CLASS_ASSERT(!link || (c->state & CLASS_LINKED));
+       assert(!link || (c->state & CLASS_LINKED));
 
        return c;
 }
@@ -481,22 +814,27 @@ static classinfo *get_array_class(utf *name,java_objectheader *initloader,
 
 classinfo *class_array_of(classinfo *component, bool link)
 {
-    s4 namelen;
-    char *namebuf;
+       classloader_t     *cl;
+    s4                 namelen;
+    char              *namebuf;
+       utf               *u;
+       classinfo         *c;
+
+       cl = component->classloader;
 
     /* Assemble the array class name */
     namelen = component->name->blength;
     
     if (component->name->text[0] == '[') {
         /* the component is itself an array */
-        namebuf = DMNEW(char, namelen + 1);
+        namebuf = MNEW(char, namelen + 1);
         namebuf[0] = '[';
         MCOPY(namebuf + 1, component->name->text, char, namelen);
         namelen++;
-
-    } else {
+    }
+       else {
         /* the component is a non-array class */
-        namebuf = DMNEW(char, namelen + 3);
+        namebuf = MNEW(char, namelen + 3);
         namebuf[0] = '[';
         namebuf[1] = 'L';
         MCOPY(namebuf + 2, component->name->text, char, namelen);
@@ -504,10 +842,13 @@ classinfo *class_array_of(classinfo *component, bool link)
         namelen += 3;
     }
 
-       return get_array_class(utf_new(namebuf, namelen),
-                                                  component->classloader,
-                                                  component->classloader,
-                                                  link);
+       u = utf_new(namebuf, namelen);
+
+       MFREE(namebuf, char, namelen);
+
+       c = get_array_class(u, cl, cl, link);
+
+       return c;
 }
 
 
@@ -522,6 +863,7 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
 {
     s4 namelen;
     char *namebuf;
+       classinfo *c;
 
        if (dim < 1) {
                log_text("Invalid array dimension requested");
@@ -533,13 +875,13 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
     
     if (element->name->text[0] == '[') {
         /* the element is itself an array */
-        namebuf = DMNEW(char, namelen + dim);
+        namebuf = MNEW(char, namelen + dim);
         memcpy(namebuf + dim, element->name->text, namelen);
         namelen += dim;
     }
     else {
         /* the element is a non-array class */
-        namebuf = DMNEW(char, namelen + 2 + dim);
+        namebuf = MNEW(char, namelen + 2 + dim);
         namebuf[dim] = 'L';
         memcpy(namebuf + dim + 1, element->name->text, namelen);
         namelen += (2 + dim);
@@ -547,10 +889,16 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
     }
        memset(namebuf, '[', dim);
 
-       return get_array_class(utf_new(namebuf, namelen),
-                                                  element->classloader,
-                                                  element->classloader,
-                                                  link);
+       utf* u = utf_new(namebuf, namelen);
+
+       MFREE(namebuf, char, namelen);
+
+       c = get_array_class(u,
+                                               element->classloader,
+                                               element->classloader,
+                                               link);
+
+       return c;
 }
 
 
@@ -575,9 +923,9 @@ constant_classref *class_lookup_classref(classinfo *cls, utf *name)
        extra_classref *xref;
        int count;
 
-       CLASS_ASSERT(cls);
-       CLASS_ASSERT(name);
-       CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
+       assert(cls);
+       assert(name);
+       assert(!cls->classrefcount || cls->classrefs);
        
        /* first search the main classref table */
        count = cls->classrefcount;
@@ -618,8 +966,8 @@ constant_classref *class_get_classref(classinfo *cls, utf *name)
        constant_classref *ref;
        extra_classref *xref;
 
-       CLASS_ASSERT(cls);
-       CLASS_ASSERT(name);
+       assert(cls);
+       assert(name);
 
        ref = class_lookup_classref(cls,name);
        if (ref)
@@ -676,22 +1024,23 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
 {
     s4 namelen;
     char *namebuf;
+       constant_classref *cr;
 
-       CLASS_ASSERT(ref);
-       CLASS_ASSERT(dim >= 1 && dim <= 255);
+       assert(ref);
+       assert(dim >= 1 && dim <= 255);
 
     /* Assemble the array class name */
     namelen = ref->name->blength;
     
     if (ref->name->text[0] == '[') {
         /* the element is itself an array */
-        namebuf = DMNEW(char, namelen + dim);
+        namebuf = MNEW(char, namelen + dim);
         memcpy(namebuf + dim, ref->name->text, namelen);
         namelen += dim;
     }
     else {
         /* the element is a non-array class */
-        namebuf = DMNEW(char, namelen + 2 + dim);
+        namebuf = MNEW(char, namelen + 2 + dim);
         namebuf[dim] = 'L';
         memcpy(namebuf + dim + 1, ref->name->text, namelen);
         namelen += (2 + dim);
@@ -699,7 +1048,13 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
     }
        memset(namebuf, '[', dim);
 
-    return class_get_classref(ref->referer,utf_new(namebuf, namelen));
+       utf* u = utf_new(namebuf, namelen);
+
+       MFREE(namebuf, char, namelen);
+
+    cr = class_get_classref(ref->referer, u);
+
+       return cr;
 }
 
 
@@ -724,7 +1079,7 @@ constant_classref *class_get_classref_component_of(constant_classref *ref)
        s4 namelen;
        char *name;
        
-       CLASS_ASSERT(ref);
+       assert(ref);
 
        name = ref->name->text;
        if (*name++ != '[')
@@ -766,51 +1121,6 @@ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
 }
 
 
-/************************* Function: class_findmethod_approx ******************
-       
-       like class_findmethod but ignores the return value when comparing the
-       descriptor.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
-{
-       s4 i;
-
-       for (i = 0; i < c->methodscount; i++) {
-               if (c->methods[i].name == name) {
-                       utf *meth_descr = c->methods[i].descriptor;
-                       
-                       if (desc == NULL) 
-                               /* ignore type */
-                               return &(c->methods[i]);
-
-                       if (desc->blength <= meth_descr->blength) {
-                               /* current position in utf text   */
-                               char *desc_utf_ptr = desc->text;      
-                               char *meth_utf_ptr = meth_descr->text;                                    
-                               /* points behind utf strings */
-                               char *desc_end = UTF_END(desc);         
-                               char *meth_end = UTF_END(meth_descr);   
-                               char ch;
-
-                               /* compare argument types */
-                               while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
-
-                                       if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
-                                               break; /* no match */
-
-                                       if (ch == ')')
-                                               return &(c->methods[i]); /* all parameter types equal */
-                               }
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-
 /* class_resolvemethod *********************************************************
        
    Searches a class and it's super classes for a method.
@@ -839,7 +1149,7 @@ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
                if (name == utf_init || name == utf_clinit)
                        return NULL;
 
-               c = c->super.cls;
+               c = c->super;
        }
 
        return NULL;
@@ -857,22 +1167,25 @@ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
 {
        methodinfo *m;
        s4          i;
-       
+
+       /* try to find the method in the class */
+
        m = class_findmethod(c, name, desc);
 
-       if (m)
+       if (m != NULL)
                return m;
 
-       /* try the superinterfaces */
+       /* No method found?  Try the super interfaces. */
 
        for (i = 0; i < c->interfacescount; i++) {
-               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
-                                                                                               name, desc);
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
 
-               if (m)
+               if (m != NULL)
                        return m;
        }
-       
+
+       /* no method found */
+
        return NULL;
 }
 
@@ -888,17 +1201,14 @@ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
 *******************************************************************************/
 
 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
-                                                                        classinfo *referer, bool except)
+                                                                        classinfo *referer, bool throwexception)
 {
        classinfo  *cls;
        methodinfo *m;
        s4          i;
 
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
 /*     if (c->flags & ACC_INTERFACE) { */
-/*             if (except) */
+/*             if (throwexception) */
 /*                     *exceptionptr = */
 /*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
 /*             return NULL; */
@@ -910,28 +1220,27 @@ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
 
        m = class_resolvemethod(cls, name, desc);
 
-       if (m)
+       if (m != NULL)
                goto found;
 
-       /* try the superinterfaces */
+       /* Try the super interfaces. */
 
        for (i = 0; i < c->interfacescount; i++) {
-               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
-                                                                                                name, desc);
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
 
-               if (m)
+               if (m != NULL)
                        goto found;
        }
        
-       if (except)
-               *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
 
        return NULL;
 
  found:
        if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
-               if (except)
-                       *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+               if (throwexception)
+                       exceptions_throw_abstractmethoderror();
 
                return NULL;
        }
@@ -953,36 +1262,31 @@ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
 *******************************************************************************/
 
 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
-                                                                                classinfo *referer, bool except)
+                                                                                classinfo *referer, bool throwexception)
 {
        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);
+               if (throwexception)
+                       exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
 
                return NULL;
        }
 
        mi = class_resolveinterfacemethod_intern(c, name, desc);
 
-       if (mi)
+       if (mi != NULL)
                return mi;
 
        /* try class java.lang.Object */
 
        mi = class_findmethod(class_java_lang_Object, name, desc);
 
-       if (mi)
+       if (mi != NULL)
                return mi;
 
-       if (except)
-               *exceptionptr =
-                       exceptions_new_nosuchmethoderror(c, name, desc);
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
 
        return NULL;
 }
@@ -1003,8 +1307,8 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
                if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
                        return &(c->fields[i]);
 
-       if (c->super.cls)
-               return class_findfield(c->super.cls, name, desc);
+       if (c->super != NULL)
+               return class_findfield(c->super, name, desc);
 
        return NULL;
 }
@@ -1017,41 +1321,18 @@ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
 
 *******************************************************************************/
  
-fieldinfo *class_findfield_by_name(classinfo *c, utf *name)
-{
-       s4 i;
-
-       /* get field index */
-
-       i = class_findfield_index_by_name(c, name);
-
-       /* field was not found, return */
-
-       if (i == -1)
-               return NULL;
-
-       /* return field address */
-
-       return &(c->fields[i]);
-}
-
-
-s4 class_findfield_index_by_name(classinfo *c, utf *name)
+fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
 {
-       s4 i;
+       for (int32_t i = 0; i < c->fieldscount; i++) {
+               fieldinfo* f = &(c->fields[i]);
 
-       for (i = 0; i < c->fieldscount; i++) {
-               /* compare field names */
-
-               if ((c->fields[i].name == name))
-                       return i;
+               if (f->name == name)
+                       return f;
        }
 
-       /* field was not found, raise exception */      
-
-       *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
-
-       return -1;
+       // Field not found.
+       exceptions_throw_nosuchfielderror(c, name);
+       return NULL;
 }
 
 
@@ -1077,18 +1358,19 @@ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
                }
     }
 
-       /* try superinterfaces recursively */
+       /* Try super interfaces recursively. */
 
        for (i = 0; i < c->interfacescount; i++) {
-               fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
-               if (fi)
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+               if (fi != NULL)
                        return fi;
        }
 
-       /* try superclass */
+       /* Try super class. */
 
-       if (c->super.cls)
-               return class_resolvefield_int(c->super.cls, name, desc);
+       if (c->super != NULL)
+               return class_resolvefield_int(c->super, name, desc);
 
        /* not found */
 
@@ -1100,27 +1382,19 @@ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
        
        Resolves a reference from REFERER to a field with NAME and DESC in class C.
 
-    If the field cannot be resolved the return value is NULL. If EXCEPT is
-    true *exceptionptr is set, too.
+    If the field cannot be resolved, an exception is thrown and the
+    return value is NULL.
 
 *******************************************************************************/
 
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
-                                                         classinfo *referer, bool except)
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
 {
        fieldinfo *fi;
 
-       /* XXX resolve class c */
-       /* XXX check access from REFERER to C */
-       
        fi = class_resolvefield_int(c, name, desc);
 
        if (!fi) {
-               if (except)
-                       *exceptionptr =
-                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
-                                                                                name);
-
+               exceptions_throw_nosuchfielderror(c, name);
                return NULL;
        }
 
@@ -1138,100 +1412,916 @@ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
 
 bool class_issubclass(classinfo *sub, classinfo *super)
 {
+       classinfo *c;
+
+       c = sub;
+
        for (;;) {
-               if (!sub)
+               /* We reached java/lang/Object and did not find the requested
+                  super class. */
+
+               if (c == NULL)
                        return false;
 
-               if (sub == super)
+               /* We found the requested super class. */
+
+               if (c == super)
                        return true;
 
-               sub = sub->super.cls;
+               c = c->super;
        }
 }
 
 
-#if !defined(NDEBUG)
-void class_showconstanti(classinfo *c, int ii) 
+/* class_isanysubclass *********************************************************
+
+   Checks a subclass relation between two classes. Implemented
+   interfaces are interpreted as super classes.
+
+   Return value: 1 ... sub is subclass of super
+                 0 ... otherwise
+
+*******************************************************************************/
+
+bool class_isanysubclass(classinfo *sub, classinfo *super)
 {
-       u4 i = ii;
-       voidptr e;
+       uint32_t diffval;
+       bool     result;
+
+       /* This is the trivial case. */
+
+       if (sub == super)
+               return true;
+
+       /* Primitive classes are only subclasses of themselves. */
+
+       if (class_is_primitive(sub) || class_is_primitive(super))
+               return false;
+
+       /* Check for interfaces. */
+
+       if (super->flags & ACC_INTERFACE) {
+               result = (sub->vftbl->interfacetablelength > super->index) &&
+                       (sub->vftbl->interfacetable[-super->index] != NULL);
+       }
+       else {
+               /* java.lang.Object is the only super class of any
+                  interface. */
+
+               if (sub->flags & ACC_INTERFACE)
+                       return (super == class_java_lang_Object);
+
+               Mutex_lock(linker_classrenumber_mutex);
+
+               diffval = sub->vftbl->baseval - super->vftbl->baseval;
+               result  = diffval <= (uint32_t) super->vftbl->diffval;
+
+               Mutex_unlock(linker_classrenumber_mutex);
+       }
+
+       return result;
+}
+
+
+/* class_is_assignable_from ****************************************************
+
+   Return whether an instance of the "from" class parameter would be
+   an instance of this class "to" as well.
+
+   ARGUMENTS:
+       to ..... class
+          from ... class
+
+   RETURN:
+       true .... is assignable
+          false ... is not assignable
+
+*******************************************************************************/
+
+bool class_is_assignable_from(classinfo *to, classinfo *from)
+{
+       if (!(to->state & CLASS_LINKED))
+               if (!link_class(to))
+                       return false;
+
+       if (!(from->state & CLASS_LINKED))
+               if (!link_class(from))
+                       return false;
+
+       return class_isanysubclass(from, to);
+}
+
+
+/* class_is_instance ***********************************************************
+
+   Return if the given Java object is an instance of the given class.
+
+   ARGUMENTS:
+       c ... class
+          h ... Java object
+
+   RETURN:
+       true .... is instance
+          false ... is not instance
+
+*******************************************************************************/
+
+bool class_is_instance(classinfo *c, java_handle_t *h)
+{
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return false;
+
+       return builtin_instanceof(h, c);
+}
+
+
+/* class_get_componenttype *****************************************************
+
+   Return the component class of the given class.  If the given class
+   is not an array, return NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_componenttype(classinfo *c)
+{
+       classinfo       *component;
+       arraydescriptor *ad;
+       
+       /* XXX maybe we could find a way to do this without linking. */
+       /* This way should be safe and easy, however.                */
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       ad = c->vftbl->arraydesc;
+       
+       if (ad == NULL)
+               return NULL;
+       
+       if (ad->arraytype == ARRAYTYPE_OBJECT)
+               component = ad->componentvftbl->clazz;
+       else
+               component = Primitive_get_class_by_type(ad->arraytype);
                
-       e = c->cpinfos [i];
-       printf ("#%d:  ", (int) i);
-       if (e) {
-               switch (c->cptags [i]) {
-               case CONSTANT_Class:
-                       printf("Classreference -> ");
-                       utf_display(((constant_classref*)e)->name);
-                       break;
-                               
-               case CONSTANT_Fieldref:
-                       printf("Fieldref -> "); goto displayFMIi;
-               case CONSTANT_Methodref:
-                       printf("Methodref -> "); goto displayFMIi;
-               case CONSTANT_InterfaceMethodref:
-                       printf("InterfaceMethod -> "); goto displayFMIi;
-               displayFMIi:
-                       {
-                               constant_FMIref *fmi = e;
-                               utf_display(fmi->classref->name);
-                               printf(".");
-                               utf_display(fmi->name);
-                               printf(" ");
-                               utf_display(fmi->descriptor);
-                       }
-                       break;
-
-               case CONSTANT_String:
-                       printf("String -> ");
-                       utf_display(e);
-                       break;
-               case CONSTANT_Integer:
-                       printf("Integer -> %d", (int) (((constant_integer*)e)->value));
-                       break;
-               case CONSTANT_Float:
-                       printf("Float -> %f", ((constant_float*)e)->value);
-                       break;
-               case CONSTANT_Double:
-                       printf("Double -> %f", ((constant_double*)e)->value);
-                       break;
-               case CONSTANT_Long:
-                       {
-                               u8 v = ((constant_long*)e)->value;
-#if U8_AVAILABLE
-                               printf("Long -> %ld", (long int) v);
+       return component;
+}
+
+
+/* class_get_declaredclasses ***************************************************
+
+   Return an array of declared classes of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+{
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *outername;
+       int                    declaredclasscount;  /* number of declared classes */
+       int                    pos;                     /* current declared class */
+       java_handle_objectarray_t *oa;               /* array of declared classes */
+       int                    i;
+       classinfo             *ic;
+
+       declaredclasscount = 0;
+
+       if (!class_is_primitive(c) && !class_is_array(c)) {
+               /* Determine number of declared classes. */
+
+               for (i = 0; i < c->innerclasscount; i++) {
+                       /* Get outer-class.  If the inner-class is not a member
+                          class, the outer-class is NULL. */
+
+                       outer = c->innerclass[i].outer_class;
+
+                       if (outer.any == NULL)
+                               continue;
+
+                       /* Check if outer-class is a classref or a real class and
+               get the class name from the structure. */
+
+                       outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+                       /* Outer class is this class. */
+
+                       if ((outername == c->name) &&
+                               ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+                               declaredclasscount++;
+               }
+       }
+
+       /* Allocate Class[] and check for OOM. */
+
+       oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+
+       if (oa == NULL)
+               return NULL;
+
+       for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+               inner = c->innerclass[i].inner_class;
+               outer = c->innerclass[i].outer_class;
+
+               /* Get outer-class.  If the inner-class is not a member class,
+                  the outer-class is NULL. */
+
+               if (outer.any == NULL)
+                       continue;
+
+               /* Check if outer_class is a classref or a real class and get
+                  the class name from the structure. */
+
+               outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+               /* Outer class is this class. */
+
+               if ((outername == c->name) &&
+                       ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+
+                       ic = resolve_classref_or_classinfo_eager(inner, false);
+
+                       if (ic == NULL)
+                               return NULL;
+
+                       if (!(ic->state & CLASS_LINKED))
+                               if (!link_class(ic))
+                                       return NULL;
+
+                       LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+               }
+       }
+
+       return oa;
+}
+
+
+/**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c          class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+{
+       methodinfo*                m;
+       java_handle_objectarray_t* oa;
+       java_handle_t*             rc;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* Determine number of constructors. */
+
+       count = 0;
+
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init))
+                       count++;
+       }
+
+       /* Create array of constructors. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the constructors and store them in the array. */
+
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init)) {
+                       // Create a java.lang.reflect.Constructor object.
+
+                       rc = java_lang_reflect_Constructor_create(m);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, rc);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
+/* class_get_declaredfields ****************************************************
+
+   Return an array of declared fields of the given class.
+
+   ARGUMENTS:
+       c ............ class to get the fields of
+          publicOnly ... show only public fields
+
+   RETURN:
+       array of java.lang.reflect.Field
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+{
+       java_handle_objectarray_t *oa;
+       fieldinfo                 *f;
+       java_handle_t             *h;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* Determine number of fields. */
+
+       count = 0;
+
+       for (i = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+                       count++;
+
+       /* Create array of fields. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the fields and store them in the array. */
+
+       for (i = 0, index = 0; i < c->fieldscount; i++) {
+               f = &(c->fields[i]);
+
+               if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+                       // Create a java.lang.reflect.Field object.
+
+                       h = java_lang_reflect_Field_create(f);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, h);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
+/* class_get_declaredmethods ***************************************************
+
+   Return an array of declared methods of the given class.
+
+   ARGUMENTS:
+       c ............ class to get the methods of
+          publicOnly ... show only public methods
+
+   RETURN:
+       array of java.lang.reflect.Method
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+{
+       java_handle_objectarray_t *oa;         /* result: array of Method-objects */
+       methodinfo                *m;     /* the current method to be represented */
+       java_handle_t             *h;
+       int                        count;
+       int                        index;
+       int                        i;
+
+       /* JOWENN: array classes do not declare methods according to mauve
+          test.  It should be considered, if we should return to my old
+          clone method overriding instead of declaring it as a member
+          function. */
+
+       if (class_is_array(c))
+               return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+       /* Determine number of methods. */
+
+       count = 0;
+
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA))
+                       count++;
+       }
+
+       /* Create array of methods. */
+
+       oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+       if (oa == NULL)
+               return NULL;
+
+       /* Get the methods and store them in the array. */
+
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA)) {
+                       // Create java.lang.reflect.Method object.
+
+                       h = java_lang_reflect_Method_create(m);
+
+                       /* Store object into array. */
+
+                       array_objectarray_element_set(oa, index, h);
+                       index++;
+               }
+       }
+
+       return oa;
+}
+#endif
+
+
+/* class_get_declaringclass ****************************************************
+
+   If the class or interface given is a member of another class,
+   return the declaring class.  For array and primitive classes return
+   NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_declaringclass(classinfo *c)
+{
+       classref_or_classinfo  cr;
+       classinfo             *dc;
+
+       /* Get declaring class. */
+
+       cr = c->declaringclass;
+
+       if (cr.any == NULL)
+               return NULL;
+
+       /* Resolve the class if necessary. */
+
+       if (IS_CLASSREF(cr)) {
+/*             dc = resolve_classref_eager(cr.ref); */
+               dc = resolve_classref_or_classinfo_eager(cr, true);
+
+               if (dc == NULL)
+                       return NULL;
+
+               /* Store the resolved class in the class structure. */
+
+               cr.cls = dc;
+       }
+
+       dc = cr.cls;
+
+       return dc;
+}
+
+
+/* class_get_enclosingclass ****************************************************
+
+   Return the enclosing class for the given class.
+
+*******************************************************************************/
+
+classinfo *class_get_enclosingclass(classinfo *c)
+{
+       classref_or_classinfo  cr;
+       classinfo             *ec;
+
+       /* Get enclosing class. */
+
+       cr = c->enclosingclass;
+
+       if (cr.any == NULL)
+               return NULL;
+
+       /* Resolve the class if necessary. */
+
+       if (IS_CLASSREF(cr)) {
+/*             ec = resolve_classref_eager(cr.ref); */
+               ec = resolve_classref_or_classinfo_eager(cr, true);
+
+               if (ec == NULL)
+                       return NULL;
+
+               /* Store the resolved class in the class structure. */
+
+               cr.cls = ec;
+       }
+
+       ec = cr.cls;
+
+       return ec;
+}
+
+
+/**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingconstructor(classinfo *c)
+{
+       methodinfo*    m;
+       java_handle_t* rc;
+
+       m = class_get_enclosingmethod_raw(c);
+
+       if (m == NULL)
+               return NULL;
+
+       /* Check for <init>. */
+
+       if (m->name != utf_init)
+               return NULL;
+
+       // Create a java.lang.reflect.Constructor object.
+
+       rc = java_lang_reflect_Constructor_create(m);
+
+       return rc;
+}
+#endif
+
+
+/* class_get_enclosingmethod ***************************************************
+
+   Return the enclosing method for the given class.
+
+   IN:
+       c ... class to return the enclosing method for
+
+   RETURN:
+       methodinfo of the enclosing method
+
+*******************************************************************************/
+
+methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+{
+       constant_nameandtype *cn;
+       classinfo            *ec;
+       methodinfo           *m;
+
+       /* get enclosing class and method */
+
+       ec = class_get_enclosingclass(c);
+       cn = c->enclosingmethod;
+
+       /* check for enclosing class and method */
+
+       if (ec == NULL)
+               return NULL;
+
+       if (cn == NULL)
+               return NULL;
+
+       /* find method in enclosing class */
+
+       m = class_findmethod(ec, cn->name, cn->descriptor);
+
+       if (m == NULL) {
+               exceptions_throw_internalerror("Enclosing method doesn't exist");
+               return NULL;
+       }
+
+       return m;
+}
+
+
+/**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingmethod(classinfo *c)
+{
+       methodinfo*    m;
+       java_handle_t* rm;
+
+       m = class_get_enclosingmethod_raw(c);
+
+       if (m == NULL)
+               return NULL;
+
+       /* check for <init> */
+
+       if (m->name == utf_init)
+               return NULL;
+
+       // Create a java.lang.reflect.Method object.
+
+       rm = java_lang_reflect_Method_create(m);
+
+       return rm;
+}
+#endif
+
+
+/* class_get_interfaces ********************************************************
+
+   Return an array of interfaces of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+{
+       classinfo                 *ic;
+       java_handle_objectarray_t *oa;
+       u4                         i;
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+
+       if (oa == NULL)
+               return NULL;
+
+       for (i = 0; i < c->interfacescount; i++) {
+               ic = c->interfaces[i];
+
+               LLNI_array_direct(oa, i) = (java_object_t *) ic;
+       }
+
+       return oa;
+}
+
+
+/* class_get_annotations *******************************************************
+
+   Get the unparsed declared annotations in a byte array
+   of the given class.
+
+   IN:
+       c........the class of which the annotations should be returned
+
+   RETURN VALUE:
+       The unparsed declared annotations in a byte array
+       (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *class_get_annotations(classinfo *c)
+{
+#if defined(ENABLE_ANNOTATIONS)
+       java_handle_t *annotations; /* unparsed annotations */
+
+       LLNI_classinfo_field_get(c, annotations, annotations);
+
+       return (java_handle_bytearray_t*)annotations;
 #else
-                               printf("Long -> HI: %ld, LO: %ld\n", 
-                                           (long int) v.high, (long int) v.low);
-#endif 
-                       }
-                       break;
-               case CONSTANT_NameAndType:
-                       { 
-                               constant_nameandtype *cnt = e;
-                               printf("NameAndType: ");
-                               utf_display(cnt->name);
-                               printf(" ");
-                               utf_display(cnt->descriptor);
+       return NULL;
+#endif
+}
+
+
+/* class_get_modifiers *********************************************************
+
+   Get the modifier flags of the given class.
+
+   IN:
+       c....the class of which the modifier flags should be returned
+          ignoreInnerClassesAttrib
+   RETURN VALUE:
+       modifier flags
+
+*******************************************************************************/
+
+int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
+{
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *innername;
+       int                    i;
+
+       if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+               /* search for passed class as inner class */
+
+               for (i = 0; i < c->innerclasscount; i++) {
+                       inner = c->innerclass[i].inner_class;
+                       outer = c->innerclass[i].outer_class;
+
+                       /* Check if inner is a classref or a real class and get
+               the name of the structure */
+
+                       innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+
+                       /* innerclass is this class */
+
+                       if (innername == c->name) {
+                               /* has the class actually an outer class? */
+
+                               if (outer.any)
+                                       /* return flags got from the outer class file */
+                                       return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
+                               else
+                                       return c->flags & ACC_CLASS_REFLECT_MASK;
                        }
-                       break;
-               case CONSTANT_Utf8:
-                       printf("Utf8 -> ");
-                       utf_display(e);
-                       break;
-               default: 
-                       log_text("Invalid type of ConstantPool-Entry");
-                       assert(0);
                }
        }
+
+       /* passed class is no inner class or it was not requested */
+
+       return c->flags & ACC_CLASS_REFLECT_MASK;
+}
+
+
+/* class_get_signature *********************************************************
+
+   Return the signature of the given class.  For array and primitive
+   classes return NULL.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+utf *class_get_signature(classinfo *c)
+{
+       /* For array and primitive classes return NULL. */
+
+       if (class_is_array(c) || class_is_primitive(c))
+               return NULL;
+
+       return c->signature;
+}
+#endif
+
+
+/* class_printflags ************************************************************
+
+   Prints flags of a class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_printflags(classinfo *c)
+{
+       if (c == NULL) {
+               printf("NULL");
+               return;
+       }
+
+       if (c->flags & ACC_PUBLIC)       printf(" PUBLIC");
+       if (c->flags & ACC_PRIVATE)      printf(" PRIVATE");
+       if (c->flags & ACC_PROTECTED)    printf(" PROTECTED");
+       if (c->flags & ACC_STATIC)       printf(" STATIC");
+       if (c->flags & ACC_FINAL)        printf(" FINAL");
+       if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+       if (c->flags & ACC_VOLATILE)     printf(" VOLATILE");
+       if (c->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
+       if (c->flags & ACC_NATIVE)       printf(" NATIVE");
+       if (c->flags & ACC_INTERFACE)    printf(" INTERFACE");
+       if (c->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
+}
+#endif
+
+
+/* class_print *****************************************************************
+
+   Prints classname plus flags.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_print(classinfo *c)
+{
+       if (c == NULL) {
+               printf("NULL");
+               return;
+       }
+
+       utf_display_printable_ascii(c->name);
+       class_printflags(c);
+}
+#endif
+
+
+/* class_classref_print ********************************************************
+
+   Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_print(constant_classref *cr)
+{
+       if (cr == NULL) {
+               printf("NULL");
+               return;
+       }
+
+       utf_display_printable_ascii(cr->name);
+       printf("(ref.by ");
+       if (cr->referer)
+               class_print(cr->referer);
+       else
+               printf("NULL");
+       printf(")");
+}
+#endif
+
+
+/* class_println ***************************************************************
+
+   Prints classname plus flags and new line.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_println(classinfo *c)
+{
+       class_print(c);
+       printf("\n");
+}
+#endif
+
+
+/* class_classref_println ******************************************************
+
+   Prints classname plus referer class and new line.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_println(constant_classref *cr)
+{
+       class_classref_print(cr);
        printf("\n");
 }
+#endif
+
+
+/* class_classref_or_classinfo_print *******************************************
+
+   Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_or_classinfo_print(classref_or_classinfo c)
+{
+       if (c.any == NULL) {
+               printf("(classref_or_classinfo) NULL");
+               return;
+       }
+       if (IS_CLASSREF(c))
+               class_classref_print(c.ref);
+       else
+               class_print(c.cls);
+}
+#endif
+
 
+/* class_classref_or_classinfo_println *****************************************
 
+   Prints classname plus referer class and a newline.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_or_classinfo_println(classref_or_classinfo c)
+{
+       class_classref_or_classinfo_print(c);
+       printf("\n");
+}
+#endif
+
+
+/* class_showconstantpool ******************************************************
+
+   Dump the constant pool of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
 void class_showconstantpool (classinfo *c) 
 {
        u4 i;
-       voidptr e;
+       void* e;
 
        printf ("---- dump of constant pool ----\n");
 
@@ -1244,29 +2334,23 @@ void class_showconstantpool (classinfo *c)
                        switch (c -> cptags [i]) {
                        case CONSTANT_Class:
                                printf ("Classreference -> ");
-                               utf_display ( ((constant_classref*)e) -> name );
+                               utf_display_printable_ascii ( ((constant_classref*)e) -> name );
                                break;
-                               
                        case CONSTANT_Fieldref:
-                               printf ("Fieldref -> "); goto displayFMI;
+                               printf ("Fieldref -> ");
+                               field_fieldref_print((constant_FMIref *) e);
+                               break;
                        case CONSTANT_Methodref:
-                               printf ("Methodref -> "); goto displayFMI;
+                               printf ("Methodref -> ");
+                               method_methodref_print((constant_FMIref *) e);
+                               break;
                        case CONSTANT_InterfaceMethodref:
-                               printf ("InterfaceMethod -> "); goto displayFMI;
-                       displayFMI:
-                               {
-                                       constant_FMIref *fmi = e;
-                                       utf_display ( fmi->classref->name );
-                                       printf (".");
-                                       utf_display ( fmi->name);
-                                       printf (" ");
-                                       utf_display ( fmi->descriptor );
-                               }
+                               printf ("InterfaceMethod -> ");
+                               method_methodref_print((constant_FMIref *) e);
                                break;
-
                        case CONSTANT_String:
                                printf ("String -> ");
-                               utf_display (e);
+                               utf_display_printable_ascii (e);
                                break;
                        case CONSTANT_Integer:
                                printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
@@ -1278,28 +2362,20 @@ void class_showconstantpool (classinfo *c)
                                printf ("Double -> %f", ((constant_double*)e) -> value);
                                break;
                        case CONSTANT_Long:
-                               {
-                                       u8 v = ((constant_long*)e) -> value;
-#if U8_AVAILABLE
-                                       printf ("Long -> %ld", (long int) v);
-#else
-                                       printf ("Long -> HI: %ld, LO: %ld\n", 
-                                                       (long int) v.high, (long int) v.low);
-#endif 
-                               }
+                               printf ("Long -> %ld", (long int) ((constant_long*)e) -> value);
                                break;
                        case CONSTANT_NameAndType:
                                {
                                        constant_nameandtype *cnt = e;
                                        printf ("NameAndType: ");
-                                       utf_display (cnt->name);
+                                       utf_display_printable_ascii (cnt->name);
                                        printf (" ");
-                                       utf_display (cnt->descriptor);
+                                       utf_display_printable_ascii (cnt->descriptor);
                                }
                                break;
                        case CONSTANT_Utf8:
                                printf ("Utf8 -> ");
-                               utf_display (e);
+                               utf_display_printable_ascii (e);
                                break;
                        default: 
                                log_text("Invalid type of ConstantPool-Entry");
@@ -1310,51 +2386,61 @@ void class_showconstantpool (classinfo *c)
                printf ("\n");
        }
 }
+#endif /* !defined(NDEBUG) */
+
 
+/* class_showmethods ***********************************************************
 
+   Dump info about the fields and methods of the given class to stdout.
 
-/********** Function: class_showmethods   (debugging only) *************/
+*******************************************************************************/
 
+#if !defined(NDEBUG)
 void class_showmethods (classinfo *c)
 {
        s4 i;
        
-       printf ("--------- Fields and Methods ----------------\n");
-       printf ("Flags: ");     printflags (c->flags);  printf ("\n");
+       printf("--------- Fields and Methods ----------------\n");
+       printf("Flags: ");
+       class_printflags(c);
+       printf("\n");
 
-       printf ("This: "); utf_display (c->name); printf ("\n");
-       if (c->super.cls) {
-               printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
-               }
-       printf ("Index: %d\n", c->index);
+       printf("This: ");
+       utf_display_printable_ascii(c->name);
+       printf("\n");
+
+       if (c->super) {
+               printf("Super: ");
+               utf_display_printable_ascii(c->super->name);
+               printf ("\n");
+       }
+
+       printf("Index: %d\n", c->index);
        
-       printf ("interfaces:\n");       
-       for (i=0; i < c-> interfacescount; i++) {
-               printf ("   ");
-               utf_display (c -> interfaces[i].cls -> name);
-               printf (" (%d)\n", c->interfaces[i].cls -> index);
-               }
+       printf("Interfaces:\n");        
+       for (i = 0; i < c->interfacescount; i++) {
+               printf("   ");
+               utf_display_printable_ascii(c->interfaces[i]->name);
+               printf (" (%d)\n", c->interfaces[i]->index);
+       }
 
-       printf ("fields:\n");           
-       for (i=0; i < c -> fieldscount; i++) {
-               field_display (&(c -> fields[i]));
-               }
+       printf("Fields:\n");
+       for (i = 0; i < c->fieldscount; i++)
+               field_println(&(c->fields[i]));
 
-       printf ("methods:\n");
-       for (i=0; i < c -> methodscount; i++) {
+       printf("Methods:\n");
+       for (i = 0; i < c->methodscount; i++) {
                methodinfo *m = &(c->methods[i]);
-               if ( !(m->flags & ACC_STATIC)) 
-                       printf ("vftblindex: %d   ", m->vftblindex);
 
-               method_display ( m );
+               if (!(m->flags & ACC_STATIC))
+                       printf("vftblindex: %d   ", m->vftblindex);
 
-               }
+               method_println(m);
+       }
 
        printf ("Virtual function table:\n");
-       for (i=0; i<c->vftbl->vftbllength; i++) {
-               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
-               }
-
+       for (i = 0; i < c->vftbl->vftbllength; i++)
+               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]));
 }
 #endif /* !defined(NDEBUG) */
 
@@ -1370,4 +2456,5 @@ void class_showmethods (classinfo *c)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */