* src/vm/initialize.c: Moved to C++.
[cacao.git] / src / vm / class.c
index 6376b8f0a47cd5b086ee24ae7b870fcda9926995..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 2299 2005-04-14 05:17:27Z edwin $
 
-*/
+#include "config.h"
 
 #include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
-#include "vm/global.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/loader.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.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/tables.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 ****************************************************/
+#include "vm/jit/asmpart.h"
 
-/* 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_io_Serializable = NULL;
+/* class_set_packagename *******************************************************
 
+   Derive the package name from the class name and store it in the
+   struct.
 
-/* system exception classes required in cacao */
+   An internal package name consists of the package name plus the
+   trailing '/', e.g. "java/lang/".
 
-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_OutOfMemoryError = NULL;
+   For classes in the unnamed package, the package name is set to
+   NULL.
 
-classinfo *class_java_lang_Exception = NULL;
-classinfo *class_java_lang_ClassNotFoundException = 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;
+void class_set_packagename(classinfo *c)
+{
+       char *p;
+       char *start;
 
-/* some classes which may be used more often */
+       p     = UTF_END(c->name) - 1;
+       start = c->name->text;
 
-classinfo *class_java_util_Vector = NULL;
+       if (c->name->text[0] == '[') {
+               /* Set packagename of arrays to the element's package. */
 
+               for (; *start == '['; start++);
 
-/* pseudo classes for the typechecker */
+               /* Skip the 'L' in arrays of references. */
 
-classinfo *pseudo_class_Arraystub = NULL;
-classinfo *pseudo_class_Null = NULL;
-classinfo *pseudo_class_New = NULL;
+               if (*start == 'L')
+                       start++;
+       }
 
-/* class_set_packagename *******************************************************
+       /* Search for last '/'. */
 
-   Derive the package name from the class name and store it in the struct.
+       for (; (p > start) && (*p != '/'); --p);
 
-*******************************************************************************/
+       /* If we found a '/' we set the package name plus the trailing
+          '/'.  Otherwise we set the packagename to NULL. */
 
-void class_set_packagename(classinfo *c)
-{
-       if (c->name->text[0] == '[') {
-               /* Array classes are not loaded from classfiles. */
-               c->packagename = array_packagename;
-       } 
-       else {
-               /* Find the package name */
-               /* Classes in the unnamed package keep packagename == NULL. */
-               char *p = utf_end(c->name) - 1;
-               char *start = c->name->text;
-               for (;p > start; --p) {
-                       if (*p == '/') {
-                               c->packagename = utf_new(start, p - start);
-                               break;
-                       }
-               }
-       }
+       if (p > start)
+               c->packagename = utf_new(start, p - start + 1);
+       else
+               c->packagename = NULL;
 }
 
+
 /* class_create_classinfo ******************************************************
 
    Create a new classinfo struct. The class name is set to the given utf *,
@@ -169,72 +127,483 @@ 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 (initverbose) {
-               char logtext[MAXLOGTEXT];
-               sprintf(logtext, "Creating class: ");
-               utf_sprint_classname(logtext + strlen(logtext), classname);
-               log_text(logtext);
-       }
+#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(classinfo, 1); /*JOWENN: NEW*/
-       /*c=NEW(classinfo);*/
-       c->vmClass = 0;
-       c->flags = 0;
        c->name = classname;
-       c->packagename = NULL;
-       c->cpcount = 0;
-       c->cptags = NULL;
-       c->cpinfos = NULL;
-       c->classrefs = NULL;
-       c->extclassrefs = NULL;
-       c->classrefcount = 0;
-       c->parseddescs = NULL;
-       c->parseddescsize = 0;
-       c->super.any = NULL;
-       c->sub = NULL;
-       c->nextsub = NULL;
-       c->interfacescount = 0;
-       c->interfaces = NULL;
-       c->fieldscount = 0;
-       c->fields = NULL;
-       c->methodscount = 0;
-       c->methods = NULL;
-       c->linked = false;
-       c->loaded = false;
-       c->index = 0;
-       c->instancesize = 0;
-       c->header.vftbl = NULL;
-       c->innerclasscount = 0;
-       c->innerclass = NULL;
-       c->vftbl = NULL;
-       c->initialized = false;
-       c->initializing = false;
-       c->classvftbl = false;
-    c->classUsed = 0;
-    c->impldBy = NULL;
-       c->classloader = NULL;
-       c->sourcefile = NULL;
-       
-       if (classname != utf_not_named_yet) {
+
+       /* 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 != 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);
+
+       Lockword_init(&(c->object.header.lockword));
+
+       return c;
+}
+
+
+/* class_postset_header_vftbl **************************************************
+
+   Set the header.vftbl of all classes created before java.lang.Class
+   was linked.  This is necessary that Java code can use a class as
+   object.
+
+*******************************************************************************/
+
+void class_postset_header_vftbl(void)
+{
+       classinfo *c;
+       u4 slot;
+       classcache_name_entry *nmen;
+       classcache_class_entry *clsen;
+
+       assert(class_java_lang_Class);
+
+       for (slot = 0; slot < hashtable_classcache.size; slot++) {
+               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+               for (; nmen; nmen = nmen->hashlink) {
+                       /* iterate over all class entries */
+
+                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                               c = clsen->classobj;
+
+                               /* now set the the vftbl */
+
+                               if (c->object.header.vftbl == NULL)
+                                       c->object.header.vftbl = class_java_lang_Class->vftbl;
+                       }
+               }
+       }
+}
+
+/* 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(USE_THREADS) && defined(NATIVE_THREADS)
-       initObjectLock(&c->header);
+#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 **************************************************************
 
        Frees all resources used by this classes Constant Pool.
@@ -245,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++) {
@@ -283,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);
 }
 
 
@@ -295,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;
        }
 
@@ -315,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;
        }
                
@@ -347,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) {
@@ -395,37 +767,39 @@ void class_free(classinfo *c)
 /* get_array_class *************************************************************
 
    Returns the array class with the given name for the given
-   classloader.
+   classloader, or NULL if an exception occurred.
+
+   Note: This function does eager loading. 
 
 *******************************************************************************/
 
-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;
        
        /* lookup this class in the classcache */
        c = classcache_lookup(initloader,name);
-       if (c)
-               return c;
-       c = classcache_lookup_defined(defloader,name);
-       if (c)
-               return c;
-
-       /* we have to create it */
-       c = class_create_classinfo(name);
-       if (!load_newly_created_array(c,initloader))
-               return NULL;
+       if (!c)
+               c = classcache_lookup_defined(defloader,name);
+
+       if (!c) {
+               /* we have to create it */
+               c = class_create_classinfo(name);
+               c = load_newly_created_array(c,initloader);
+               if (c == NULL)
+                       return NULL;
+       }
 
-       CLASS_ASSERT(c);
-       CLASS_ASSERT(c->loaded);
-       CLASS_ASSERT(c->classloader == defloader);
+       assert(c);
+       assert(c->state & CLASS_LOADED);
+       assert(c->classloader == defloader);
 
-       if (link && !c->linked)
+       if (link && !(c->state & CLASS_LINKED))
                if (!link_class(c))
                        return NULL;
 
-       CLASS_ASSERT(!link || c->linked);
+       assert(!link || (c->state & CLASS_LINKED));
 
        return c;
 }
@@ -440,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);
@@ -463,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;
 }
 
 
@@ -481,22 +863,25 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
 {
     s4 namelen;
     char *namebuf;
+       classinfo *c;
 
-       if (dim < 1)
-               panic("Invalid array dimension requested");
+       if (dim < 1) {
+               log_text("Invalid array dimension requested");
+               assert(0);
+       }
 
     /* Assemble the array class name */
     namelen = element->name->blength;
     
     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);
@@ -504,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;
 }
 
 
@@ -532,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;
@@ -575,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)
@@ -592,14 +983,33 @@ constant_classref *class_get_classref(classinfo *cls, utf *name)
 }
 
 
-/* class_get_classref_multiarray_of ********************************************
+/* class_get_self_classref *****************************************************
 
-   Returns an array type reference with the given dimension and element class
-   reference.
+   Returns the constant_classref to the class itself.
 
    IN:
-       dim..............the requested dimension
-                           dim must be in [1;255]. This is NOT checked!
+       cls..............the class containing the reference
+
+   RETURN VALUE:
+       a pointer to a constant_classref (never NULL)
+
+*******************************************************************************/
+
+constant_classref *class_get_self_classref(classinfo *cls)
+{
+       /* XXX this should be done in a faster way. Maybe always make */
+       /* the classref of index 0 a self reference.                  */
+       return class_get_classref(cls,cls->name);
+}
+
+/* class_get_classref_multiarray_of ********************************************
+
+   Returns an array type reference with the given dimension and element class
+   reference.
+
+   IN:
+       dim..............the requested dimension
+                           dim must be in [1;255]. This is NOT checked!
           ref..............the component class reference
 
    RETURN VALUE:
@@ -614,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);
@@ -637,9 +1048,16 @@ 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;
 }
 
+
 /* class_get_classref_component_of *********************************************
 
    Returns the component classref of a given array type reference
@@ -661,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++ != '[')
@@ -680,6 +1098,1353 @@ constant_classref *class_get_classref_component_of(constant_classref *ref)
 }
 
 
+/* class_findmethod ************************************************************
+       
+   Searches a 'classinfo' structure for a method having the given name
+   and descriptor. If descriptor is NULL, it is ignored.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+{
+       methodinfo *m;
+       s4          i;
+
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+
+               if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
+                       return m;
+       }
+
+       return NULL;
+}
+
+
+/* class_resolvemethod *********************************************************
+       
+   Searches a class and it's super classes for a method.
+
+   Superinterfaces are *not* searched.
+
+*******************************************************************************/
+
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+{
+       methodinfo *m;
+
+       while (c) {
+               m = class_findmethod(c, name, desc);
+
+               if (m)
+                       return m;
+
+               /* JVM Specification bug: 
+
+                  It is important NOT to resolve special <init> and <clinit>
+                  methods to super classes or interfaces; yet, this is not
+                  explicited in the specification.  Section 5.4.3.3 should be
+                  updated appropriately.  */
+
+               if (name == utf_init || name == utf_clinit)
+                       return NULL;
+
+               c = c->super;
+       }
+
+       return NULL;
+}
+
+
+/* class_resolveinterfacemethod_intern *****************************************
+
+   Internally used helper function. Do not use this directly.
+
+*******************************************************************************/
+
+static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
+                                                                                                          utf *name, utf *desc)
+{
+       methodinfo *m;
+       s4          i;
+
+       /* try to find the method in the class */
+
+       m = class_findmethod(c, name, desc);
+
+       if (m != NULL)
+               return m;
+
+       /* No method found?  Try the super interfaces. */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+               if (m != NULL)
+                       return m;
+       }
+
+       /* no method found */
+
+       return NULL;
+}
+
+
+/* class_resolveclassmethod ****************************************************
+       
+   Resolves a reference from REFERER to a method with NAME and DESC in
+   class C.
+
+   If the method cannot be resolved the return value is NULL. If
+   EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+                                                                        classinfo *referer, bool throwexception)
+{
+       classinfo  *cls;
+       methodinfo *m;
+       s4          i;
+
+/*     if (c->flags & ACC_INTERFACE) { */
+/*             if (throwexception) */
+/*                     *exceptionptr = */
+/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
+/*             return NULL; */
+/*     } */
+
+       /* try class c and its superclasses */
+
+       cls = c;
+
+       m = class_resolvemethod(cls, name, desc);
+
+       if (m != NULL)
+               goto found;
+
+       /* Try the super interfaces. */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+               if (m != NULL)
+                       goto found;
+       }
+       
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
+
+       return NULL;
+
+ found:
+       if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+               if (throwexception)
+                       exceptions_throw_abstractmethoderror();
+
+               return NULL;
+       }
+
+       /* XXX check access rights */
+
+       return m;
+}
+
+
+/* class_resolveinterfacemethod ************************************************
+
+   Resolves a reference from REFERER to a method with NAME and DESC in
+   interface C.
+
+   If the method cannot be resolved the return value is NULL. If
+   EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+                                                                                classinfo *referer, bool throwexception)
+{
+       methodinfo *mi;
+
+       if (!(c->flags & ACC_INTERFACE)) {
+               if (throwexception)
+                       exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
+
+               return NULL;
+       }
+
+       mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+       if (mi != NULL)
+               return mi;
+
+       /* try class java.lang.Object */
+
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+
+       if (mi != NULL)
+               return mi;
+
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
+
+       return NULL;
+}
+
+
+/* class_findfield *************************************************************
+       
+   Searches for field with specified name and type in a classinfo
+   structure. If no such field is found NULL is returned.
+
+*******************************************************************************/
+
+fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
+{
+       s4 i;
+
+       for (i = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
+                       return &(c->fields[i]);
+
+       if (c->super != NULL)
+               return class_findfield(c->super, name, desc);
+
+       return NULL;
+}
+
+
+/* class_findfield_approx ******************************************************
+       
+   Searches in 'classinfo'-structure for a field with the specified
+   name.
+
+*******************************************************************************/
+fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
+{
+       for (int32_t i = 0; i < c->fieldscount; i++) {
+               fieldinfo* f = &(c->fields[i]);
+
+               if (f->name == name)
+                       return f;
+       }
+
+       // Field not found.
+       exceptions_throw_nosuchfielderror(c, name);
+       return NULL;
+}
+
+
+/****************** Function: class_resolvefield_int ***************************
+
+    This is an internally used helper function. Do not use this directly.
+
+       Tries to resolve a field having the given name and type.
+    If the field cannot be resolved, NULL is returned.
+
+*******************************************************************************/
+
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+{
+       fieldinfo *fi;
+       s4         i;
+
+       /* search for field in class c */
+
+       for (i = 0; i < c->fieldscount; i++) { 
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+                       return &(c->fields[i]);
+               }
+    }
+
+       /* Try super interfaces recursively. */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+               if (fi != NULL)
+                       return fi;
+       }
+
+       /* Try super class. */
+
+       if (c->super != NULL)
+               return class_resolvefield_int(c->super, name, desc);
+
+       /* not found */
+
+       return NULL;
+}
+
+
+/********************* Function: class_resolvefield ***************************
+       
+       Resolves a reference from REFERER to a field with NAME and DESC in class C.
+
+    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)
+{
+       fieldinfo *fi;
+
+       fi = class_resolvefield_int(c, name, desc);
+
+       if (!fi) {
+               exceptions_throw_nosuchfielderror(c, name);
+               return NULL;
+       }
+
+       /* XXX check access rights */
+
+       return fi;
+}
+
+
+/* class_issubclass ************************************************************
+
+   Checks if sub is a descendant of super.
+       
+*******************************************************************************/
+
+bool class_issubclass(classinfo *sub, classinfo *super)
+{
+       classinfo *c;
+
+       c = sub;
+
+       for (;;) {
+               /* We reached java/lang/Object and did not find the requested
+                  super class. */
+
+               if (c == NULL)
+                       return false;
+
+               /* We found the requested super class. */
+
+               if (c == super)
+                       return true;
+
+               c = c->super;
+       }
+}
+
+
+/* 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)
+{
+       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);
+               
+       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
+       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;
+                       }
+               }
+       }
+
+       /* 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;
+       void* e;
+
+       printf ("---- dump of constant pool ----\n");
+
+       for (i=0; i<c->cpcount; i++) {
+               printf ("#%d:  ", (int) i);
+               
+               e = c -> cpinfos [i];
+               if (e) {
+                       
+                       switch (c -> cptags [i]) {
+                       case CONSTANT_Class:
+                               printf ("Classreference -> ");
+                               utf_display_printable_ascii ( ((constant_classref*)e) -> name );
+                               break;
+                       case CONSTANT_Fieldref:
+                               printf ("Fieldref -> ");
+                               field_fieldref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_Methodref:
+                               printf ("Methodref -> ");
+                               method_methodref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_InterfaceMethodref:
+                               printf ("InterfaceMethod -> ");
+                               method_methodref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_String:
+                               printf ("String -> ");
+                               utf_display_printable_ascii (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:
+                               printf ("Long -> %ld", (long int) ((constant_long*)e) -> value);
+                               break;
+                       case CONSTANT_NameAndType:
+                               {
+                                       constant_nameandtype *cnt = e;
+                                       printf ("NameAndType: ");
+                                       utf_display_printable_ascii (cnt->name);
+                                       printf (" ");
+                                       utf_display_printable_ascii (cnt->descriptor);
+                               }
+                               break;
+                       case CONSTANT_Utf8:
+                               printf ("Utf8 -> ");
+                               utf_display_printable_ascii (e);
+                               break;
+                       default: 
+                               log_text("Invalid type of ConstantPool-Entry");
+                               assert(0);
+                       }
+               }
+
+               printf ("\n");
+       }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* class_showmethods ***********************************************************
+
+   Dump info about the fields and methods of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_showmethods (classinfo *c)
+{
+       s4 i;
+       
+       printf("--------- Fields and Methods ----------------\n");
+       printf("Flags: ");
+       class_printflags(c);
+       printf("\n");
+
+       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_printable_ascii(c->interfaces[i]->name);
+               printf (" (%d)\n", c->interfaces[i]->index);
+       }
+
+       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++) {
+               methodinfo *m = &(c->methods[i]);
+
+               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]));
+}
+#endif /* !defined(NDEBUG) */
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -691,4 +2456,5 @@ constant_classref *class_get_classref_component_of(constant_classref *ref)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */