* renamed CACAO_TYPECHECK to ENABLE_VERIFIER
[cacao.git] / src / vm / class.c
index c99158a2c09e5f13cdf5723b36ccff7c653f617c..7dc4da84adc8c343e0b6beace38936d50bc3af0a 100644 (file)
             Andreas Krall
             Christian Thalinger
 
-   $Id: class.c 2323 2005-04-21 22:18:38Z twisti $
+   $Id: class.c 3807 2005-11-26 21:51:11Z edwin $
 
 */
 
 #include <assert.h>
 #include <string.h>
 
-#include "vm/global.h"
+#include "config.h"
+#include "vm/types.h"
+
 #include "mm/memory.h"
 
 #if defined(USE_THREADS)
 #include "vm/class.h"
 #include "vm/classcache.h"
 #include "vm/exceptions.h"
+#include "vm/global.h"
 #include "vm/loader.h"
 #include "vm/options.h"
 #include "vm/resolve.h"
 #include "vm/statistics.h"
+#include "vm/stringlocal.h"
 #include "vm/tables.h"
 #include "vm/utf8.h"
 
@@ -93,7 +97,9 @@ 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;
 
 
@@ -103,10 +109,14 @@ 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;
@@ -118,10 +128,23 @@ 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;
+
 
 /* pseudo classes for the typechecker */
 
@@ -129,6 +152,7 @@ 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.
@@ -137,24 +161,33 @@ classinfo *pseudo_class_New = NULL;
 
 void class_set_packagename(classinfo *c)
 {
+       char *p = UTF_END(c->name) - 1;
+       char *start = c->name->text;
+
+       /* set the package name */
+       /* classes in the unnamed package keep packagename == NULL */
+
        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;
-                       }
-               }
+               /* set packagename of arrays to the element's package */
+
+               for (; *start == '['; start++);
+
+               /* skip the 'L' in arrays of references */
+               if (*start == 'L')
+                       start++;
+
+               for (; (p > start) && (*p != '/'); --p);
+
+               c->packagename = utf_new(start, p - start);
+
+       } else {
+               for (; (p > start) && (*p != '/'); --p);
+
+               c->packagename = utf_new(start, p - start);
        }
 }
 
+
 /* class_create_classinfo ******************************************************
 
    Create a new classinfo struct. The class name is set to the given utf *,
@@ -179,55 +212,24 @@ classinfo *class_create_classinfo(utf *classname)
        if (!classname)
                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 (initverbose)
+               log_message_utf("Creating class: ", classname);
+
+       /* GCNEW_UNCOLLECTABLE clears the allocated memory */
 
-       c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
+       c = GCNEW_UNCOLLECTABLE(classinfo, 1);
        /*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;
+
+       /* 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)
+                       c->header.vftbl = class_java_lang_Class->vftbl;
        
-       if (classname != utf_not_named_yet) {
+       if (classname != utf_not_named_yet)
                class_set_packagename(c);
-       }
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
        initObjectLock(&c->header);
@@ -236,6 +238,43 @@ classinfo *class_create_classinfo(utf *classname)
        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 < classcache_hash.size; slot++) {
+               nmen = (classcache_name_entry *) classcache_hash.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->header.vftbl == NULL)
+                                       c->header.vftbl = class_java_lang_Class->vftbl;
+                       }
+               }
+       }
+}
+
+
 /* class_freepool **************************************************************
 
        Frees all resources used by this classes Constant Pool.
@@ -396,7 +435,9 @@ 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. 
 
 *******************************************************************************/
 
@@ -407,16 +448,16 @@ static classinfo *get_array_class(utf *name,java_objectheader *initloader,
        
        /* 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);
@@ -483,8 +524,10 @@ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
     s4 namelen;
     char *namebuf;
 
-       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;
@@ -593,6 +636,25 @@ constant_classref *class_get_classref(classinfo *cls, utf *name)
 }
 
 
+/* class_get_self_classref *****************************************************
+
+   Returns the constant_classref to the class itself.
+
+   IN:
+       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
@@ -641,6 +703,7 @@ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *r
     return class_get_classref(ref->referer,utf_new(namebuf, namelen));
 }
 
+
 /* class_get_classref_component_of *********************************************
 
    Returns the component classref of a given array type reference
@@ -681,6 +744,620 @@ 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;
+}
+
+
+/************************* 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.
+
+   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.cls;
+       }
+
+       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;
+       
+       m = class_findmethod(c, name, desc);
+
+       if (m)
+               return m;
+
+       /* try the superinterfaces */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
+                                                                                               name, desc);
+
+               if (m)
+                       return m;
+       }
+       
+       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 except)
+{
+       classinfo  *cls;
+       methodinfo *m;
+       s4          i;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+/*     if (c->flags & ACC_INTERFACE) { */
+/*             if (except) */
+/*                     *exceptionptr = */
+/*                             new_exception(string_java_lang_IncompatibleClassChangeError); */
+/*             return NULL; */
+/*     } */
+
+       /* try class c and its superclasses */
+
+       cls = c;
+
+       m = class_resolvemethod(cls, name, desc);
+
+       if (m)
+               goto found;
+
+       /* try the superinterfaces */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
+                                                                                                name, desc);
+
+               if (m)
+                       goto found;
+       }
+       
+       if (except)
+               *exceptionptr = exceptions_new_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);
+
+               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 except)
+{
+       methodinfo *mi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+       if (!(c->flags & ACC_INTERFACE)) {
+               if (except)
+                       *exceptionptr =
+                               new_exception(string_java_lang_IncompatibleClassChangeError);
+
+               return NULL;
+       }
+
+       mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+       if (mi)
+               return mi;
+
+       /* try class java.lang.Object */
+
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+
+       if (mi)
+               return mi;
+
+       if (except)
+               *exceptionptr =
+                       exceptions_new_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.cls)
+               return class_findfield(c->super.cls, 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)
+{
+       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)
+{
+       s4 i;
+
+       for (i = 0; i < c->fieldscount; i++) {
+               /* compare field names */
+
+               if ((c->fields[i].name == name))
+                       return i;
+       }
+
+       /* field was not found, raise exception */      
+
+       *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
+
+       return -1;
+}
+
+
+/****************** 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 superinterfaces recursively */
+
+       for (i = 0; i < c->interfacescount; i++) {
+               fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
+               if (fi)
+                       return fi;
+       }
+
+       /* try superclass */
+
+       if (c->super.cls)
+               return class_resolvefield_int(c->super.cls, 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 the return value is NULL. If EXCEPT is
+    true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
+                                                         classinfo *referer, bool except)
+{
+       fieldinfo *fi;
+
+       /* XXX resolve class c */
+       /* XXX check access from REFERER to C */
+       
+       fi = class_resolvefield_int(c, name, desc);
+
+       if (!fi) {
+               if (except)
+                       *exceptionptr =
+                               new_exception_utfmessage(string_java_lang_NoSuchFieldError,
+                                                                                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)
+{
+       for (;;) {
+               if (!sub)
+                       return false;
+
+               if (sub == super)
+                       return true;
+
+               sub = sub->super.cls;
+       }
+}
+
+
+void class_showconstanti(classinfo *c, int ii) 
+{
+       u4 i = ii;
+       voidptr e;
+               
+       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);
+#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);
+                       }
+                       break;
+               case CONSTANT_Utf8:
+                       printf("Utf8 -> ");
+                       utf_display(e);
+                       break;
+               default: 
+                       log_text("Invalid type of ConstantPool-Entry");
+                       assert(0);
+               }
+       }
+       printf("\n");
+}
+
+
+void class_showconstantpool (classinfo *c) 
+{
+       u4 i;
+       voidptr 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 ( ((constant_classref*)e) -> name );
+                               break;
+                               
+                       case CONSTANT_Fieldref:
+                               printf ("Fieldref -> "); goto displayFMI;
+                       case CONSTANT_Methodref:
+                               printf ("Methodref -> "); goto displayFMI;
+                       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 );
+                               }
+                               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);
+#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);
+                               }
+                               break;
+                       case CONSTANT_Utf8:
+                               printf ("Utf8 -> ");
+                               utf_display (e);
+                               break;
+                       default: 
+                               log_text("Invalid type of ConstantPool-Entry");
+                               assert(0);
+                       }
+               }
+
+               printf ("\n");
+       }
+}
+
+
+
+/********** Function: class_showmethods   (debugging only) *************/
+
+void class_showmethods (classinfo *c)
+{
+       s4 i;
+       
+       printf ("--------- Fields and Methods ----------------\n");
+       printf ("Flags: ");     printflags (c->flags);  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 ("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 ("fields:\n");           
+       for (i=0; i < c -> fieldscount; i++) {
+               field_display (&(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_display ( 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]) );
+               }
+
+}
+
+
 /*
  * 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