* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / native / vm / VMClass.c
index c7ac871e8747f432ef16e48b7cae9cdbc9612638..6ca26c0af31dd6678dcf288f6a83dbbf4ba24805 100644 (file)
@@ -1,9 +1,9 @@
-/* nat/VMClass.c - java/lang/Class
+/* src/native/vm/VMClass.c - java/lang/VMClass
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    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
+   Contact: cacao@cacaojvm.org
 
    Authors: Roman Obermaiser
 
    Changes: Joseph Wenninger
+            Christian Thalinger
 
-   $Id: VMClass.c 1323 2004-07-18 21:42:11Z motse $
+   $Id: VMClass.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
 
 #include <string.h>
-#include "jni.h"
-#include "types.h"
-#include "global.h"
-#include "builtin.h"
-#include "loader.h"
-#include "native.h"
-#include "tables.h"
-#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-#include "java_lang_Object.h"
-#include "java_lang_Class.h"
-#include "java_lang_ClassLoader.h"
-#include "java_security_ProtectionDomain.h"
-#include "java_lang_reflect_Constructor.h"
-#include "java_lang_reflect_Field.h"
-#include "java_lang_reflect_Method.h"
-#include "java_lang_Throwable.h"    /* needed for java_lang_VMClass.h */
-#include "java_lang_VMClass.h"
-
 
-/* for selecting public members */
-#define MEMBER_PUBLIC  0
+#include "config.h"
+#include "vm/types.h"
+
+#include "mm/memory.h"
+#include "native/jni.h"
+#include "native/native.h"
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_ClassLoader.h"
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_VMClass.h"
+#include "native/include/java_lang_reflect_Constructor.h"
+#include "native/include/java_lang_reflect_Field.h"
+#include "native/include/java_lang_reflect_Method.h"
+#include "native/include/java_security_ProtectionDomain.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/initialize.h"
+#include "vm/loader.h"
+#include "vm/resolve.h"
+#include "vm/stringlocal.h"
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    forName
- * Signature: (Ljava/lang/String;)Ljava/lang/Class;
+ * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *s)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
 {
        classinfo *c;
-       utf *u;
+       utf       *u;
+       u2        *pos;
+       s4         i;
 
        /* illegal argument */
-       if (!s)
+
+       if (!name)
                return NULL;
-       
+
+       /* name must not contain '/' (mauve test) */
+
+       for (i = 0, pos = name->value->data + name->offset; i < name->count; i++, pos++) {
+               if (*pos == '/') {
+                       *exceptionptr =
+                               new_exception_javastring(string_java_lang_ClassNotFoundException, name);
+                       return NULL;
+               }
+       }
+
        /* create utf string in which '.' is replaced by '/' */
-       u = javastring_toutf(s, true);
 
-       /* create a new class, ... */
-       c = class_new(u);
+       u = javastring_toutf(name, true);
+
+       /* try to load, ... */
 
-       /* load, ... */
-       if (!class_load(c)) {
+       if (!(c = load_class_from_classloader(u, (java_objectheader *) loader))) {
                classinfo *xclass;
 
                xclass = (*exceptionptr)->vftbl->class;
@@ -87,604 +101,522 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, j
                /* if the exception is a NoClassDefFoundError, we replace it with a
                   ClassNotFoundException, otherwise return the exception */
 
-               if (xclass == class_get(utf_new_char(string_java_lang_NoClassDefFoundError))) {
+               if (xclass == class_java_lang_NoClassDefFoundError) {
                        /* clear exceptionptr, because builtin_new checks for 
                           ExceptionInInitializerError */
                        *exceptionptr = NULL;
 
                        *exceptionptr =
-                               new_exception_javastring(string_java_lang_ClassNotFoundException, s);
+                               new_exception_javastring(string_java_lang_ClassNotFoundException, name);
                }
 
            return NULL;
        }
 
        /* link, ... */
-       if (!class_link(c))
+
+       if (!link_class(c))
                return NULL;
        
-       /* ...and initialize it */
-       if (!class_init(c))
-               return NULL;
+       /* ...and initialize it, if required */
 
-       use_class_as_object(c);
+       if (initialize)
+               if (!initialize_class(c))
+                       return NULL;
 
        return (java_lang_Class *) c;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getClassLoader
  * Signature: ()Ljava/lang/ClassLoader;
  */
-JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *that)
-{  
-       return ((classinfo*)that)->classloader;
-/*     init_systemclassloader();
+JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *klass)
+{
+       classinfo *c;
+
+       c = (classinfo *) klass;
 
-       return SystemClassLoader;*/
+       return (java_lang_ClassLoader *) c->classloader;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getComponentType
  * Signature: ()Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz,java_lang_Class *that)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-    classinfo *thisclass = (classinfo *) that;
-    classinfo *c = NULL;
-    arraydescriptor *desc;
-    
-    if ((desc = thisclass->vftbl->arraydesc) != NULL) {
-        if (desc->arraytype == ARRAYTYPE_OBJECT)
-            c = desc->componentvftbl->class;
-        else
-            c = primitivetype_table[desc->arraytype].class_primitive;
-        
-        /* set vftbl */
-               use_class_as_object(c);
-    }
-    
-    return (java_lang_Class *) c;
+       classinfo       *c;
+       classinfo       *comp;
+       arraydescriptor *desc;
+       
+       c = (classinfo *) klass;
+       desc = c->vftbl->arraydesc;
+       
+       if (desc == NULL)
+               return NULL;
+       
+       if (desc->arraytype == ARRAYTYPE_OBJECT)
+               comp = desc->componentvftbl->class;
+       else
+               comp = primitivetype_table[desc->arraytype].class_primitive;
+               
+       return (java_lang_Class *) comp;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getDeclaredConstructors
  * Signature: (Z)[Ljava/lang/reflect/Constructor;
  */
-JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz,
-       struct java_lang_Class *that, s4 public_only)
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
 {
-  
-    classinfo *c = (classinfo *) that;
-    java_objectheader *o;
-    classinfo *class_constructor;
-    java_objectarray *array_constructor;     /* result: array of Method-objects */
-    java_objectarray *exceptiontypes;   /* the exceptions thrown by the method */
-    methodinfo *m;                     /* the current method to be represented */    
-    int public_methods = 0;            /* number of public methods of the class */
-    int pos = 0;
-    int i;
-    utf *utf_constr = utf_new_char("<init>");
-
-    /* determine number of constructors */
-    for (i = 0; i < c->methodscount; i++) 
-               if (((c->methods[i].flags & ACC_PUBLIC) || !public_only) && 
-                       (c->methods[i].name == utf_constr))
-                       public_methods++;
+       classinfo                     *c;
+       methodinfo                    *m; /* the current method to be represented */
+       java_objectarray              *oa;     /* result: array of Method-objects */
+       java_objectheader             *o;
+       java_lang_reflect_Constructor *rc;
+       s4 public_methods;               /* number of public methods of the class */
+       s4 pos;
+       s4 i;
 
-    class_constructor = class_new(utf_new_char("java/lang/reflect/Constructor"));
+       c = (classinfo *) klass;
 
-       if (!class_constructor->loaded)
-               class_load(class_constructor);
+       /* determine number of constructors */
 
-       if (!class_constructor->linked)
-               class_link(class_constructor);
+       for (i = 0, public_methods = 0; i < c->methodscount; i++) {
+               m = &c->methods[i];
 
-    array_constructor = builtin_anewarray(public_methods, class_constructor);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init))
+                       public_methods++;
+       }
+
+       oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
 
-    if (!array_constructor
+       if (!oa
                return NULL;
 
-    for (i = 0; i < c->methodscount; i++) 
-               if ((c->methods[i].flags & ACC_PUBLIC) || !public_only){
-                       m = &c->methods[i];         
-                       if (m->name!=utf_constr)
-                               continue;
+       for (i = 0, pos = 0; i < c->methodscount; i++) {
+               m = &c->methods[i];
 
-                       o = native_new_and_init(class_constructor);     
-                       array_constructor->data[pos++] = o;
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init)) {
 
-                       /* array of exceptions declared to be thrown, information not available !! */
-                       exceptiontypes = builtin_anewarray(0, class_java_lang_Class);
+                       if (!(o = native_new_and_init(class_java_lang_reflect_Constructor)))
+                               return NULL;
 
-                       /*          class_showconstantpool(class_constructor);*/
                        /* initialize instance fields */
-                       /*          ((java_lang_reflect_Constructor*)o)->flag=(m->flags & (ACC_PRIVATE | ACC_PUBLIC | ACC_PROTECTED));*/
-                       setfield_critical(class_constructor,o,"clazz",          "Ljava/lang/Class;",  jobject, (jobject) c /*this*/);
-                       setfield_critical(class_constructor,o,"slot",           "I",                 jint,    i); 
-                       /*          setfield_critical(class_constructor,o,"flag",           "I",                     jint,    (m->flags & (ACC_PRIVATE | 
-                                       ACC_PUBLIC | ACC_PROTECTED))); */
-                       setfield_critical(class_constructor,o,"exceptionTypes", "[Ljava/lang/Class;", jobject, (jobject) exceptiontypes);
-           setfield_critical(class_constructor,o,"parameterTypes", "[Ljava/lang/Class;", jobject, (jobject) get_parametertypes(m));
-        }           
-    
-       return array_constructor;
+
+                       rc = (java_lang_reflect_Constructor *) o;
+
+                       rc->clazz = (java_lang_Class *) c;
+                       rc->slot  = i;
+
+                       /* store object into array */
+
+                       oa->data[pos++] = o;
+               }
+       }
+
+       return oa;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getDeclaredClasses
  * Signature: (Z)[Ljava/lang/Class;
  */
-JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 publicOnly)
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
 {
-#if defined(__GNUC__)
-#warning fix the public only case
-#endif
-       classinfo *c = (classinfo *) that;
-       int pos = 0;                /* current declared class */
-       int declaredclasscount = 0; /* number of declared classes */
-       java_objectarray *result;   /* array of declared classes */
-       int notPublicOnly = !publicOnly;
-       int i;
-
-       if (!that)
-               return NULL;
-
-       /*printf("PublicOnly: %d\n",publicOnly);*/
-       if (!Java_java_lang_VMClass_isPrimitive(env, clazz, (java_lang_Class *) c) && (c->name->text[0] != '[')) {
+       classinfo             *c;
+       classref_or_classinfo  outer;
+       utf                   *outername;
+       s4                     declaredclasscount;  /* number of declared classes */
+       s4                     pos;                     /* current declared class */
+       java_objectarray      *oa;                   /* array of declared classes */
+       s4                     i;
+
+       c = (classinfo *) klass;
+       declaredclasscount = 0;
+
+       if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
+               (c->name->text[0] != '[')) {
                /* determine number of declared classes */
+
                for (i = 0; i < c->innerclasscount; i++) {
-                       if ( (c->innerclass[i].outer_class == c) && (notPublicOnly || (c->innerclass[i].flags & ACC_PUBLIC)))
-                               /* outer class is this class */
+                       outer = c->innerclass[i].outer_class;
+
+                       /* 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++;
                }
        }
 
-       /*class_showmethods(c); */
+       /* allocate Class[] and check for OOM */
 
-       result = builtin_anewarray(declaredclasscount, class_java_lang_Class);          
+       oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
 
-       for (i = 0; i < c->innerclasscount; i++) {
-               classinfo *inner = c->innerclass[i].inner_class;
-               classinfo *outer = c->innerclass[i].outer_class;
-               
-               if ((outer == c) && (notPublicOnly || (inner->flags & ACC_PUBLIC))) {
-                       /* outer class is this class, store innerclass in array */
-                       use_class_as_object(inner);
-                       result->data[pos++] = (java_objectheader *) inner;
+       if (!oa)
+               return NULL;
+
+       for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+               outer = c->innerclass[i].outer_class;
+
+               /* 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))) {
+                       classinfo *inner;
+
+                       if (!resolve_classref_or_classinfo(NULL,
+                                                                                          c->innerclass[i].inner_class,
+                                                                                          resolveEager, false, false,
+                                                                                          &inner))
+                               return NULL;
+
+                       if (!(inner->state & CLASS_LINKED))
+                               if (!link_class(inner))
+                                       return NULL;
+
+                       oa->data[pos++] = (java_objectheader *) inner;
                }
        }
 
-       return result;
+       return oa;
 }
 
 
 /*
- * Class:     java/lang/Class
+ * Class:     java/lang/VMClass
  * Method:    getDeclaringClass
  * Signature: ()Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, struct java_lang_Class *that)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-#if defined(__GNUC__)
-#warning fixme
-#endif
-       classinfo *c = (classinfo *) that;
+       classinfo             *c;
+       classref_or_classinfo  inner;
+       utf                   *innername;
+       classinfo             *outer;
+       s4                     i;
+
+       c = (classinfo *) klass;
 
-       if (that && !Java_java_lang_VMClass_isPrimitive(env, clazz,that) && (c->name->text[0] != '[')) {
-               int i;
+       if (!Java_java_lang_VMClass_isPrimitive(env, clazz, klass) &&
+               (c->name->text[0] != '[')) {
 
                if (c->innerclasscount == 0)  /* no innerclasses exist */
                        return NULL;
     
                for (i = 0; i < c->innerclasscount; i++) {
-                       classinfo *inner =  c->innerclass[i].inner_class;
-                       classinfo *outer =  c->innerclass[i].outer_class;
-      
-                       if (inner == c) {
-                               /* innerclass is this class */
-                               use_class_as_object(outer);
+                       inner = c->innerclass[i].inner_class;
+
+                       /* check if inner_class is a classref or a real class and
+               get the class name from the structure */
+
+                       innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+
+                       /* innerclass is this class */
+
+                       if (innername == c->name) {
+                               /* maybe the outer class is not loaded yet */
+
+                               if (!resolve_classref_or_classinfo(NULL,
+                                                                                                  c->innerclass[i].outer_class,
+                                                                                                  resolveEager, false, false,
+                                                                                                  &outer))
+                                       return NULL;
+
+                               if (!(outer->state & CLASS_LINKED))
+                                       if (!link_class(outer))
+                                               return NULL;
+
                                return (java_lang_Class *) outer;
                        }
                }
        }
 
        /* return NULL for arrayclasses and primitive classes */
-       return NULL;
-}
-
-
-java_lang_reflect_Field* cacao_getField0(JNIEnv *env, java_lang_Class *that, java_lang_String *name, s4 public_only)
-{
-    classinfo *c;
-       classinfo *fieldtype;
-    fieldinfo *f;               /* the field to be represented */
-    java_lang_reflect_Field *o; /* result: field-object */
-    utf *desc;                         /* the fielddescriptor */
-    int idx;
-
-    /* create Field object */
-/*      c = (classinfo *) loader_load(utf_new_char("java/lang/reflect/Field")); */
-    c = class_new(utf_new_char("java/lang/reflect/Field"));
-    o = (java_lang_reflect_Field *) native_new_and_init(c);
-
-    /* get fieldinfo entry */
-    idx = class_findfield_index_approx((classinfo *) that, javastring_toutf(name, false));
-
-    if (idx < 0) {
-           *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
-           return NULL;
-       }
 
-    f = &(((classinfo *) that)->fields[idx]);
-    if (f) {
-               if (public_only && !(f->flags & ACC_PUBLIC)) {
-                       /* field is not public  and public only had been requested*/
-                       *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
-                       return NULL;
-               }
-
-               desc = f->descriptor;
-               fieldtype = class_from_descriptor(desc->text, utf_end(desc), NULL, CLASSLOAD_LOAD);
-               if (!fieldtype)
-                       return NULL;
-        
-               /* initialize instance fields */
-               setfield_critical(c,o,"declaringClass",          "Ljava/lang/Class;",  jobject, (jobject) that /*this*/);
-               /*      ((java_lang_reflect_Field*)(o))->flag=f->flags;*/
-               /* save type in slot-field for faster processing */
-               /* setfield_critical(c,o,"flag",           "I",             jint,    (jint) f->flags); */
-               o->flag = f->flags;
-               setfield_critical(c,o,"slot",           "I",                jint,    (jint) idx);  
-               setfield_critical(c,o,"name",           "Ljava/lang/String;", jstring, (jstring) name);
-               /*setfield_critical(c,o,"type",           "Ljava/lang/Class;",  jclass,  fieldtype);*/
-
-               return o;
-    }
-
-    return NULL;
+       return NULL;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getDeclaredFields
  * Signature: (Z)[Ljava/lang/reflect/Field;
  */
-JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 public_only)
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
 {
-    classinfo *c = (classinfo *) that;
-    classinfo *class_field;
-    java_objectarray *array_field; /* result: array of field-objects */
-    int public_fields = 0;         /* number of elements in field-array */
-    int pos = 0;
-    int i;
-
-    /* determine number of fields */
-    for (i = 0; i < c->fieldscount; i++) 
-               if ((c->fields[i].flags & ACC_PUBLIC) || (!public_only))
+       classinfo               *c;
+       java_objectarray        *oa;            /* result: array of field-objects */
+       fieldinfo               *f;
+       java_objectheader       *o;
+       java_lang_reflect_Field *rf;
+       s4 public_fields;                    /* number of elements in field-array */
+       s4 pos;
+       s4 i;
+
+       c = (classinfo *) klass;
+
+       /* determine number of fields */
+
+       for (i = 0, public_fields = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
                        public_fields++;
 
-/*      class_field = loader_load(utf_new_char("java/lang/reflect/Field")); */
-    class_field = class_new(utf_new_char("java/lang/reflect/Field"));
+       /* create array of fields */
+
+       oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
 
-    if (!class_field) 
+       if (!oa)
                return NULL;
 
-    /* create array of fields */
-    array_field = builtin_anewarray(public_fields, class_field);
+       /* get the fields and store in the array */
 
-    /* creation of array failed */
-    if (!array_field) 
-               return NULL;
+       for (i = 0, pos = 0; i < c->fieldscount; i++) {
+               f = &(c->fields[i]);
+
+               if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+                       /* create Field object */
+
+                       if (!(o = native_new_and_init(class_java_lang_reflect_Field)))
+                               return NULL;
 
-    /* get the fields and store in the array */    
-    for (i = 0; i < c->fieldscount; i++) 
-               if ( (c->fields[i].flags & ACC_PUBLIC) || (!public_only))
-                       array_field->data[pos++] = 
-                               (java_objectheader *) cacao_getField0(env,
-                                          that, (java_lang_String *) javastring_new(c->fields[i].name),public_only);
-    return array_field;
+                       /* initialize instance fields */
+
+                       rf = (java_lang_reflect_Field *) o;
+
+                       rf->declaringClass = (java_lang_Class *) c;
+                       rf->name           = javastring_new(f->name);
+                       rf->slot           = i;
+
+                       /* store object into array */
+
+                       oa->data[pos++] = o;
+               }
+       }
+
+       return oa;
 }
 
 
 /*
- * Class:     java/lang/Class
+ * Class:     java/lang/VMClass
  * Method:    getInterfaces
  * Signature: ()[Ljava/lang/Class;
  */
-JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-       classinfo *c = (classinfo *) that;
-       u4 i;
-       java_objectarray *a;
+       classinfo        *c;
+       classinfo        *ic;
+       java_objectarray *oa;
+       u4                i;
+
+       c = (classinfo *) klass;
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
 
-       a = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+       oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
 
-       if (!a)
+       if (!oa)
                return NULL;
 
        for (i = 0; i < c->interfacescount; i++) {
-               use_class_as_object(c->interfaces[i]);
+               ic = c->interfaces[i].cls;
 
-               a->data[i] = (java_objectheader *) c->interfaces[i];
+               oa->data[i] = (java_objectheader *) ic;
        }
 
-       return a;
-}
-
-
-java_lang_reflect_Method* cacao_getMethod0(JNIEnv *env, java_lang_Class *that, java_lang_String *name, java_objectarray *types, s4 which)
-{
-    classinfo *c; 
-    classinfo *clazz = (classinfo *) that;
-    java_lang_reflect_Method* o;         /* result: Method-object */ 
-    java_objectarray *exceptiontypes;    /* the exceptions thrown by the method */
-    methodinfo *m;                      /* the method to be represented */
-
-/*      c = (classinfo *) loader_load(utf_new_char("java/lang/reflect/Method")); */
-    c = class_new(utf_new_char("java/lang/reflect/Method"));
-    o = (java_lang_reflect_Method *) native_new_and_init(c);
-
-    /* find the method */
-    m = class_resolvemethod_approx(clazz, 
-                                                                  javastring_toutf(name, false),
-                                                                  create_methodsig(types,0)
-                                                                  );
-
-    if (!m || (which == MEMBER_PUBLIC && !(m->flags & ACC_PUBLIC))) {
-               /* no apropriate method was found */
-               *exceptionptr = new_exception(string_java_lang_NoSuchMethodException);
-               return NULL;
-       }
-   
-    /* array of exceptions declared to be thrown, information not available !! */
-    exceptiontypes = builtin_anewarray(0, class_java_lang_Class);
-
-    /* initialize instance fields */
-    setfield_critical(c,o,"clazz",          "Ljava/lang/Class;",  jobject, (jobject) clazz /*this*/);
-    setfield_critical(c,o,"parameterTypes", "[Ljava/lang/Class;", jobject, (jobject) types);
-    setfield_critical(c,o,"exceptionTypes", "[Ljava/lang/Class;", jobject, (jobject) exceptiontypes);
-    setfield_critical(c,o,"name",           "Ljava/lang/String;", jstring, javastring_new(m->name));
-    setfield_critical(c,o,"modifiers",      "I",                 jint,    m->flags);
-    setfield_critical(c,o,"slot",           "I",                 jint,    0); 
-    setfield_critical(c,o,"returnType",     "Ljava/lang/Class;",  jclass,  get_returntype(m));
-
-    return o;
+       return oa;
 }
 
 
 /*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    getDeclaredMethods
  * Signature: (Z)[Ljava/lang/reflect/Method;
  */
-JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *that, s4 public_only)
+JNIEXPORT java_objectarray* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
 {
-    classinfo *c = (classinfo *) that;    
-    java_objectheader *o;
-    classinfo *class_method;
-    java_objectarray *array_method;     /* result: array of Method-objects */
-    java_objectarray *exceptiontypes;   /* the exceptions thrown by the method */
-    methodinfo *m;                     /* the current method to be represented */    
-    int public_methods = 0;            /* number of public methods of the class */
-    int pos = 0;
-    int i;
-    utf *utf_constr=utf_new_char("<init>");
-    utf *utf_clinit=utf_new_char("<clinit>");
-
-/*      class_method = (classinfo*) loader_load(utf_new_char ("java/lang/reflect/Method")); */
-    class_method = class_new(utf_new_char("java/lang/reflect/Method"));
-
-    if (!class_method) 
-               return NULL;
+       classinfo                *c;
+       java_objectheader        *o;
+       java_lang_reflect_Method *rm;
+       java_objectarray         *oa;          /* result: array of Method-objects */
+       methodinfo               *m;      /* the current method to be represented */
+       s4 public_methods;               /* number of public methods of the class */
+       s4 pos;
+       s4 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 (Java_java_lang_VMClass_isArray(env, clazz,that)) {
-               return builtin_anewarray(0, class_method);
-       }
+       c = (classinfo *) klass;    
+       public_methods = 0;
 
+       /* 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. */
 
-    /* determine number of methods */
-    for (i = 0; i < c->methodscount; i++) 
-               if ((((c->methods[i].flags & ACC_PUBLIC)) || (!public_only)) && 
-                       (!
-                        ((c->methods[i].name==utf_constr) ||
-                         (c->methods[i].name==utf_clinit) )
-                        )) public_methods++;
+       if (Java_java_lang_VMClass_isArray(env, clazz, klass))
+               return builtin_anewarray(0, class_java_lang_reflect_Method);
 
-       /*      
-               class_showmethods(class_method);
-               panic("JOWENN");
-       */
-    
+       /* determine number of methods */
 
-    array_method = builtin_anewarray(public_methods, class_method);
+       for (i = 0; i < c->methodscount; i++) {
+               m = &c->methods[i];
 
-    if (!array_method) 
-               return NULL;
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+                       ((m->name != utf_init) && (m->name != utf_clinit)))
+                       public_methods++;
+       }
 
-    for (i = 0; i < c->methodscount; i++) 
-               if (((c->methods[i].flags & ACC_PUBLIC) || (!public_only)) && 
-                       (!
-                        ((c->methods[i].name==utf_constr) ||
-                         (c->methods[i].name==utf_clinit) )
-                        )) {
+       oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
 
-                       m = &c->methods[i];         
-                       o = native_new_and_init(class_method);     
-                       array_method->data[pos++] = o;
+       if (!oa) 
+               return NULL;
+
+       for (i = 0, pos = 0; i < c->methodscount; i++) {
+               m = &c->methods[i];
 
-                       /* array of exceptions declared to be thrown, information not available !! */
-                       exceptiontypes = builtin_anewarray (0, class_java_lang_Class);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
+                       ((m->name != utf_init) && (m->name != utf_clinit))) {
 
+                       if (!(o = native_new_and_init(class_java_lang_reflect_Method)))
+                               return NULL;
 
                        /* initialize instance fields */
-                       /*          ((java_lang_reflect_Method*)o)->flag=(m->flags & 
-                                       (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_ABSTRACT | ACC_STATIC | ACC_FINAL |
-                                       ACC_SYNCHRONIZED | ACC_NATIVE | ACC_STRICT)
-                                       );*/
-                       setfield_critical(class_method,o,"declaringClass",          "Ljava/lang/Class;",  jobject, (jobject) c /*this*/);
-                       setfield_critical(class_method,o,"name",           "Ljava/lang/String;", jstring, javastring_new(m->name));
-                       /*          setfield_critical(class_method,o,"flag",      "I",               jint,   (m->flags &
-                                       (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_ABSTRACT | ACC_STATIC | ACC_FINAL |
-                                       ACC_SYNCHRONIZED | ACC_NATIVE | ACC_STRICT)));*/
-                       setfield_critical(class_method,o,"slot",           "I",              jint,    i); 
-                       /*          setfield_critical(class_method,o,"returnType",     "Ljava/lang/Class;",  jclass,  get_returntype(m));
-                                       setfield_critical(class_method,o,"exceptionTypes", "[Ljava/lang/Class;", jobject, (jobject) exceptiontypes);
-                                       setfield_critical(class_method,o,"parameterTypes", "[Ljava/lang/Class;", jobject, (jobject) get_parametertypes(m));*/
-        }           
-
-    return array_method;
+
+                       rm = (java_lang_reflect_Method *) o;
+
+                       rm->declaringClass = klass;
+                       rm->name           = javastring_new(m->name);
+                       rm->slot           = i;
+
+                       /* store object into array */
+
+                       oa->data[pos++] = o;
+               }
+       }
+
+       return oa;
 }
 
 
 /*
- * Class:     java/lang/Class
+ * Class:     java/lang/VMClass
  * Method:    getModifiers
- * Signature: ()I
+ * Signature: (Z)I
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
 {
-       classinfo *c = (classinfo *) that;
-       return c->flags;
-}
+       classinfo             *c;
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *innername;
+       s4                     i;
 
+       c = (classinfo *) klass;
 
-/*
- * Class:     java/lang/Class
- * Method:    getName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class* that)
-{
-       u4 i;
-       classinfo *c = (classinfo *) that;
-       java_lang_String *s = (java_lang_String *) javastring_new(c->name);
+       if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+               /* search for passed class as inner class */
 
-       if (!s)
-               return NULL;
+               for (i = 0; i < c->innerclasscount; i++) {
+                       inner = c->innerclass[i].inner_class;
+                       outer = c->innerclass[i].outer_class;
 
-       /* return string where '/' is replaced by '.' */
-       for (i = 0; i < s->value->header.size; i++) {
-               if (s->value->data[i] == '/')
-                       s->value->data[i] = '.';
+                       /* 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;
+                               else
+                                       return c->flags;
+                       }
+               }
        }
 
-       return s;
-       
+       /* passed class is no inner class or it was not requested */
+
+       return c->flags;
 }
 
 
 /*
  * Class:     java/lang/VMClass
- * Method:    getBeautifiedName
- * Signature: (Ljava/lang/Class;)Ljava/lang/String;
+ * Method:    getName
+ * Signature: ()Ljava/lang/String;
  */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getBeautifiedName(JNIEnv *env, jclass clazz, java_lang_Class *par1)
+JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-    u4 dimCnt;
-    classinfo *c = (classinfo *) (par1);
-
-    char *utf__ptr = c->name->text;      /* current position in utf-text */
-    char **utf_ptr = &utf__ptr;
-    char *desc_end = utf_end(c->name);   /* points behind utf string     */
-    java_lang_String *s;
-    char *str = NULL;
-    s4   len;
-    s4   i;
-    
-#if 0
-    log_text("Java_java_lang_VMClass_getBeautifiedName");
-    utf_display(c->name);
-    log_text("beautifying");
-#endif
-    dimCnt=0;
-    while ( *utf_ptr != desc_end ) {
-               if (utf_nextu2(utf_ptr)=='[') dimCnt++;
-               else break;
-    }
-    utf__ptr = (*utf_ptr) - 1;
-
-    len = 0;
-
-#if 0  
-    log_text("------>");
-    utf_display(c->name);
-    log_text("<------");
-#endif 
-
-    if (((*utf_ptr) + 1) == desc_end) {
-           for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
-                       if (primitivetype_table[i].typesig == (*utf__ptr)) {
-                               len = dimCnt * 2 + strlen(primitivetype_table[i].name);
-                               str = MNEW(char, len + 1);
-                               strcpy(str, primitivetype_table[i].name);
-                               break;
-                       }
-           }
-    }
-
-    if (len == 0) {
-               if (dimCnt>0) {
-                       len = dimCnt + strlen(c->name->text) - 2;
-                       str = MNEW(char, len + 1);
-                       strncpy(str, ++utf__ptr, len - 2 * dimCnt);        
-               } else {
-                       len = strlen(c->name->text);
-                       str = MNEW(char, len + 1);
-                       strncpy(str, utf__ptr, len);       
-               }
-               
-    }  
-
-    dimCnt = len - 2 * dimCnt;
-    str[len] = 0;
-    for (i = len - 1; i >= dimCnt; i = i - 2) {
-               str[i] = ']';
-               str[i - 1] = '[';
-    }
+       classinfo        *c;
+       java_lang_String *s;
+       u4                i;
 
-    s = javastring_new(utf_new_char(str));
-    MFREE(str, char, len + 1);
+       c = (classinfo *) klass;
+       s = (java_lang_String *) javastring_new(c->name);
 
-    if (!s) return NULL;
+       if (!s)
+               return NULL;
 
        /* return string where '/' is replaced by '.' */
+
        for (i = 0; i < s->value->header.size; i++) {
-               if (s->value->data[i] == '/') s->value->data[i] = '.';
+               if (s->value->data[i] == '/')
+                       s->value->data[i] = '.';
        }
-       
+
        return s;
 }
 
 
-
 /*
  * Class:     java/lang/Class
  * Method:    getSuperclass
  * Signature: ()Ljava/lang/Class;
  */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-       classinfo *cl = (classinfo *) that;
-       classinfo *c = cl->super;
+       classinfo *c;
+       classinfo *sc;
 
-       if (!c)
+       c = (classinfo *) klass;
+       sc = c->super.cls;
+
+       if (c->flags & ACC_INTERFACE)
                return NULL;
 
-       use_class_as_object (c);
+       if (!sc)
+               return NULL;
 
-       return (java_lang_Class *) c;
+       return (java_lang_Class *) sc;
 }
 
 
@@ -693,11 +625,15 @@ JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *
  * Method:    isArray
  * Signature: ()Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-    classinfo *c = (classinfo *) that;
+       classinfo *c = (classinfo *) klass;
 
-    return c->vftbl->arraydesc != NULL;
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return 0;
+
+       return (c->vftbl->arraydesc != NULL);
 }
 
 
@@ -706,16 +642,30 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, j
  * Method:    isAssignableFrom
  * Signature: (Ljava/lang/Class;)Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *that, java_lang_Class *sup)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
 {
-       /*      log_text("Java_java_lang_VMClass_isAssignableFrom");*/
-       
-       if (!sup) return 0;
-       if (!that) {
-               panic("sup->vmClass is NULL in VMClass.isAssignableFrom");
+       classinfo *kc;
+       classinfo *cc;
+
+       kc = (classinfo *) klass;
+       cc = (classinfo *) c;
+
+       if (cc == NULL) {
+               exceptions_throw_nullpointerexception();
                return 0;
        }
-       return (*env)->IsAssignableForm(env, (jclass) sup, (jclass) that);
+
+       if (!(kc->state & CLASS_LINKED))
+               if (!link_class(kc))
+                       return 0;
+
+       if (!(cc->state & CLASS_LINKED))
+               if (!link_class(cc))
+                       return 0;
+
+       /* XXX this may be wrong for array classes */
+
+       return builtin_isanysubclass(cc, kc);
 }
 
 
@@ -724,11 +674,19 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass
  * Method:    isInstance
  * Signature: (Ljava/lang/Object;)Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *that, java_lang_Object *obj)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
 {
-/*     classinfo *clazz = (classinfo *) that; */
+       classinfo         *c;
+       java_objectheader *ob;
+
+       c = (classinfo *) klass;
+       ob = (java_objectheader *) o;
 
-       return (*env)->IsInstanceOf(env, (jobject) obj, that);
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return 0;
+
+       return builtin_instanceof(ob, c);
 }
 
 
@@ -737,9 +695,11 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz
  * Method:    isInterface
  * Signature: ()Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-       classinfo *c = (classinfo *) that;
+       classinfo *c;
+
+       c = (classinfo *) klass;
 
        if (c->flags & ACC_INTERFACE)
                return true;
@@ -753,12 +713,15 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass claz
  * Method:    isPrimitive
  * Signature: ()Z
  */
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *that)
+JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *klass)
 {
-       int i;
-       classinfo *c = (classinfo *) that;
+       classinfo *c;
+       s4         i;
+
+       c = (classinfo *) klass;
 
        /* search table of primitive classes */
+
        for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
                if (primitivetype_table[i].class_primitive == c)
                        return true;
@@ -768,49 +731,16 @@ JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass claz
 
 
 /*
- * Class:     java_lang_VMClass
- * Method:    initialize
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMClass_initialize(JNIEnv *env, jclass clazz, java_lang_Class *c)
-{
-       classinfo *ci;
-
-       ci = (classinfo *) c;
-
-       /* initialize class */
-       if (!ci->initialized)
-               class_init(ci);
-}
-
-
-/*
- * Class:     java_lang_VMClass
- * Method:    loadArrayClass
- * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_loadArrayClass(JNIEnv *env, jclass clazz, java_lang_String *par1, java_lang_ClassLoader* par2)
-{
-       log_text("Java_java_lang_VMClass_loadArrayClass");
-
-       return 0;
-}
-
-
-/*
- * Class:     java_lang_VMClass
+ * Class:     java/lang/VMClass
  * Method:    throwException
  * Signature: (Ljava/lang/Throwable;)V
  */
-JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *par1)
+JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
 {
-       log_text("Won't implement VmClass.throwException. (Not needed according to spec) Is only needed to be bug compatible with the SUN VM. (according to gnuclasspath team)");
+       *exceptionptr = (java_objectheader *) t;
 }
 
 
-
-
-
 /*
  * 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