/* src/vmcore/class.c - class related functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: class.c 8207 2007-07-16 15:18:32Z twisti $
-
*/
#include "mm/memory.h"
+#include "native/llni.h"
+
#include "threads/lock-common.h"
#include "toolbox/logging.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vmcore/class.h"
#include "vmcore/classcache.h"
+#include "vmcore/linker.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
#include "vmcore/utf8.h"
-/* global variables ***********************************************************/
+#if defined(ENABLE_JAVASE)
+/* We need to define some reflection functions here since we cannot
+ include native/vm/reflect.h as it includes generated header
+ files. */
+
+java_object_t *reflect_constructor_new(methodinfo *m);
+java_object_t *reflect_field_new(fieldinfo *f);
+java_object_t *reflect_method_new(methodinfo *m);
+#endif
-list_t unlinkedclasses; /* this is only used for eager class */
- /* loading */
+/* global variables ***********************************************************/
/* frequently used classes ****************************************************/
-/* important system classes */
+/* Important system classes. */
classinfo *class_java_lang_Object;
classinfo *class_java_lang_Class;
classinfo *class_java_lang_System;
classinfo *class_java_lang_Thread;
classinfo *class_java_lang_ThreadGroup;
-classinfo *class_java_lang_VMSystem;
-classinfo *class_java_lang_VMThread;
-classinfo *class_java_io_Serializable;
-
-
-/* system exception classes required in cacao */
-
classinfo *class_java_lang_Throwable;
-classinfo *class_java_lang_Error;
-classinfo *class_java_lang_LinkageError;
-classinfo *class_java_lang_NoClassDefFoundError;
-classinfo *class_java_lang_OutOfMemoryError;
-classinfo *class_java_lang_VirtualMachineError;
+classinfo *class_java_io_Serializable;
-#if defined(WITH_CLASSPATH_GNU)
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_VMSystem;
+classinfo *class_java_lang_VMThread;
classinfo *class_java_lang_VMThrowable;
#endif
+/* Important system exceptions. */
+
classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_ClassCastException;
classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
#if defined(ENABLE_JAVASE)
classinfo *class_java_lang_Void;
classinfo *class_java_lang_Float;
classinfo *class_java_lang_Double;
-
-/* some runtime exception */
-
-classinfo *class_java_lang_NullPointerException;
-
-
/* some classes which may be used more often */
#if defined(ENABLE_JAVASE)
classinfo *class_java_lang_reflect_Method;
classinfo *class_java_security_PrivilegedAction;
classinfo *class_java_util_Vector;
+classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_reflect_VMConstructor;
+classinfo *class_java_lang_reflect_VMField;
+classinfo *class_java_lang_reflect_VMMethod;
+# endif
classinfo *arrayclass_java_lang_Object;
-#endif
+# if defined(ENABLE_ANNOTATIONS)
+classinfo *class_sun_reflect_ConstantPool;
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_sun_reflect_annotation_AnnotationParser;
+# endif
+# endif
+#endif
/* pseudo classes for the typechecker */
/* class_set_packagename *******************************************************
- Derive the package name from the class name and store it in the struct.
+ Derive the package name from the class name and store it in the
+ struct.
+
+ An internal package name consists of the package name plus the
+ trailing '/', e.g. "java/lang/".
+
+ For classes in the unnamed package, the package name is set to
+ NULL.
*******************************************************************************/
void class_set_packagename(classinfo *c)
{
- char *p = UTF_END(c->name) - 1;
- char *start = c->name->text;
+ char *p;
+ char *start;
- /* set the package name */
- /* classes in the unnamed package keep packagename == NULL */
+ p = UTF_END(c->name) - 1;
+ start = c->name->text;
if (c->name->text[0] == '[') {
- /* set packagename of arrays to the element's package */
+ /* Set packagename of arrays to the element's package. */
for (; *start == '['; start++);
- /* skip the 'L' in arrays of references */
+ /* Skip the 'L' in arrays of references. */
+
if (*start == 'L')
start++;
+ }
- for (; (p > start) && (*p != '/'); --p);
+ /* Search for last '/'. */
- c->packagename = utf_new(start, p - start);
+ for (; (p > start) && (*p != '/'); --p);
- } else {
- for (; (p > start) && (*p != '/'); --p);
+ /* If we found a '/' we set the package name plus the trailing
+ '/'. Otherwise we set the packagename to NULL. */
- c->packagename = utf_new(start, p - start);
- }
+ if (p > start)
+ c->packagename = utf_new(start, p - start + 1);
+ else
+ c->packagename = NULL;
}
log_message_utf("Creating class: ", classname);
#endif
+#if !defined(ENABLE_GC_BOEHM)
+ c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+ /*c = NEW(classinfo);
+ MZERO(c, classinfo, 1);*/
+#else
+ c = GCNEW_UNCOLLECTABLE(classinfo, 1);
/* GCNEW_UNCOLLECTABLE clears the allocated memory */
+#endif
- c = GCNEW_UNCOLLECTABLE(classinfo, 1);
- /*c=NEW(classinfo);*/
c->name = classname;
/* Set the header.vftbl of all loaded classes to the one of
*******************************************************************************/
-classinfo *class_define(utf *name, java_objectheader *cl, s4 length, u1 *data)
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
{
classinfo *c;
classinfo *r;
cb = NEW(classbuffer);
- cb->class = c;
+ cb->clazz = c;
cb->size = length;
cb->data = data;
cb->pos = cb->data;
return NULL;
}
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* Store the protection domain. */
+
+ c->protectiondomain = pd;
+# endif
+#endif
+
/* Store the newly defined class in the class cache. This call
also checks whether a class of the same name has already been
defined by the same defining loader, and if so, replaces the
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* check buffer size */
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* check buffer size */
bool class_load_attributes(classbuffer *cb)
{
- classinfo *c;
- u4 i, j;
- u2 attributes_count;
- u2 attribute_name_index;
- utf *attribute_name;
-
- c = cb->class;
+ 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 */
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. If an inner class is not a member, its
- outer_class is NULL, if a class is anonymous, its name is
- NULL. */
+ the access flags. */
- innerclassinfo *info = c->innerclass + j;
-
- info->inner_class.ref =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- info->outer_class.ref =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- info->name =
- innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- info->flags = suck_u2(cb);
+ 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) {
if (!loader_load_attribute_signature(cb, &(c->signature)))
return false;
}
-#if 0
- /* XXX We can't do a release with that enabled */
+#endif
+#if defined(ENABLE_ANNOTATIONS)
else if (attribute_name == utf_RuntimeVisibleAnnotations) {
/* RuntimeVisibleAnnotations */
-
- if (!annotation_load_attribute_runtimevisibleannotations(cb))
+ 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
-#endif
+
else {
/* unknown attribute */
{
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]));
-#if defined(ENABLE_CACAO_GC)
MFREE(c->fields, fieldinfo, c->fieldscount);
-#endif
}
if (c->methods) {
*******************************************************************************/
-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;
classinfo *class_array_of(classinfo *component, bool link)
{
- java_objectheader *cl;
+ classloader_t *cl;
s4 namelen;
char *namebuf;
utf *u;
classinfo *c;
- s4 dumpsize;
+ int32_t dumpmarker;
cl = component->classloader;
- dumpsize = dump_size();
+ DMARKER;
/* Assemble the array class name */
namelen = component->name->blength;
c = get_array_class(u, cl, cl, link);
- dump_release(dumpsize);
+ DRELEASE;
return c;
}
{
s4 namelen;
char *namebuf;
- s4 dumpsize;
classinfo *c;
+ int32_t dumpmarker;
- dumpsize = dump_size();
+ DMARKER;
if (dim < 1) {
log_text("Invalid array dimension requested");
element->classloader,
link);
- dump_release(dumpsize);
+ DRELEASE;
return c;
}
{
s4 namelen;
char *namebuf;
- s4 dumpsize;
constant_classref *cr;
+ int32_t dumpmarker;
assert(ref);
assert(dim >= 1 && dim <= 255);
- dumpsize = dump_size();
+ DMARKER;
/* Assemble the array class name */
namelen = ref->name->blength;
cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
- dump_release(dumpsize);
+ DRELEASE;
return cr;
}
if (name == utf_init || name == utf_clinit)
return NULL;
- c = c->super.cls;
+ c = c->super;
}
return NULL;
if (m != NULL)
return m;
- /* no method found? try the superinterfaces */
+ /* No method found? Try the super interfaces. */
for (i = 0; i < c->interfacescount; i++) {
- m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
- name, desc);
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
if (m != NULL)
return m;
if (m != NULL)
goto found;
- /* try the superinterfaces */
+ /* Try the super interfaces. */
for (i = 0; i < c->interfacescount; i++) {
- m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
- name, desc);
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
if (m != NULL)
goto found;
if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
return &(c->fields[i]);
- if (c->super.cls)
- return class_findfield(c->super.cls, name, desc);
+ if (c->super != NULL)
+ return class_findfield(c->super, name, desc);
return NULL;
}
}
}
- /* try superinterfaces recursively */
+ /* Try super interfaces recursively. */
for (i = 0; i < c->interfacescount; i++) {
- fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
- if (fi)
+ fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+ if (fi != NULL)
return fi;
}
- /* try superclass */
+ /* Try super class. */
- if (c->super.cls)
- return class_resolvefield_int(c->super.cls, name, desc);
+ if (c->super != NULL)
+ return class_resolvefield_int(c->super, name, desc);
/* not found */
bool class_issubclass(classinfo *sub, classinfo *super)
{
+ classinfo *c;
+
+ c = sub;
+
for (;;) {
- if (!sub)
+ /* We reached java/lang/Object and did not find the requested
+ super class. */
+
+ if (c == NULL)
return false;
- if (sub == super)
+ /* We found the requested super class. */
+
+ if (c == super)
return true;
- sub = sub->super.cls;
+ c = c->super;
}
}
bool class_isanysubclass(classinfo *sub, classinfo *super)
{
- castinfo classvalues;
- u4 diffval;
+ uint32_t diffval;
bool result;
/* This is the trivial case. */
if (sub->flags & ACC_INTERFACE)
return (super == class_java_lang_Object);
- ASM_GETCLASSVALUES_ATOMIC(super->vftbl, sub->vftbl, &classvalues);
+#if USES_NEW_SUBTYPE
+ result = fast_subtype_check(sub->vftbl, super->vftbl);
+#else
+ LOCK_CLASSRENUMBER_LOCK;
+
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
- diffval = classvalues.sub_baseval - classvalues.super_baseval;
- result = diffval <= (u4) classvalues.super_diffval;
+ UNLOCK_CLASSRENUMBER_LOCK;
+#endif
}
return result;
}
-/* class_is_primitive **********************************************************
+/* 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
- Checks if the given class is a primitive class.
+ RETURN:
+ true .... is assignable
+ false ... is not assignable
*******************************************************************************/
-bool class_is_primitive(classinfo *c)
+bool class_is_assignable_from(classinfo *to, classinfo *from)
{
- if (c->flags & ACC_CLASS_PRIMITIVE)
- return true;
+ if (!(to->state & CLASS_LINKED))
+ if (!link_class(to))
+ return false;
+
+ if (!(from->state & CLASS_LINKED))
+ if (!link_class(from))
+ return false;
- return false;
+ return class_isanysubclass(from, to);
}
-/* class_is_array **************************************************************
+/* class_is_instance ***********************************************************
+
+ Return if the given Java object is an instance of the given class.
+
+ ARGUMENTS:
+ c ... class
+ h ... Java object
- Checks if the given class is an array class.
+ RETURN:
+ true .... is instance
+ false ... is not instance
*******************************************************************************/
-bool class_is_array(classinfo *c)
+bool class_is_instance(classinfo *c, java_handle_t *h)
{
if (!(c->state & CLASS_LINKED))
if (!link_class(c))
return false;
- return (c->vftbl->arraydesc != NULL);
+ return builtin_instanceof(h, c);
}
-/* class_is_interface **********************************************************
+/* class_get_componenttype *****************************************************
- Checks if the given class is an interface.
+ Return the component class of the given class. If the given class
+ is not an array, return NULL.
*******************************************************************************/
-bool class_is_interface(classinfo *c)
+classinfo *class_get_componenttype(classinfo *c)
{
- if (c->flags & ACC_INTERFACE)
- return true;
+ 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_class_get_by_type(ad->arraytype);
+
+ return component;
+}
+
- return false;
+/* 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 Constructor object. This is actualy a
+ java_lang_reflect_Constructor pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ rc = reflect_constructor_new(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 Field object. This is actualy a
+ java_lang_reflect_Field pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ h = reflect_field_new(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 method object. This is actualy a
+ java_lang_reflect_Method pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ h = reflect_method_new(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,
classinfo *class_get_declaringclass(classinfo *c)
{
- classref_or_classinfo innercr;
- utf *innername;
- classref_or_classinfo outercr;
- classinfo *outer;
- int16_t i;
+ classref_or_classinfo cr;
+ classinfo *dc;
- /* return NULL for arrayclasses and primitive classes */
+ /* Get declaring class. */
- if (class_is_primitive(c) || (c->name->text[0] == '['))
+ cr = c->declaringclass;
+
+ if (cr.any == NULL)
return NULL;
- /* no innerclasses exist */
+ /* 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 ****************************************************
- if (c->innerclasscount == 0)
+ 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;
- for (i = 0; i < c->innerclasscount; i++) {
- /* Check if inner_class is a classref or a real class and get
- the class name from the structure. */
+ /* 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;
- innercr = c->innerclass[i].inner_class;
+ /* Store the resolved class in the class structure. */
- innername = IS_CLASSREF(innercr) ?
- innercr.ref->name : innercr.cls->name;
+ cr.cls = ec;
+ }
- /* Is the current innerclass this class? */
+ ec = cr.cls;
- if (innername == c->name) {
- /* Maybe the outer class is not loaded yet. */
+ return ec;
+}
- outercr = c->innerclass[i].outer_class;
- outer = resolve_classref_or_classinfo_eager(outercr, false);
+/**
+ * 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;
- if (outer == NULL)
- return NULL;
+ m = class_get_enclosingmethod_raw(c);
- if (!(outer->state & CLASS_LINKED))
- if (!link_class(outer))
- return NULL;
+ if (m == NULL)
+ return NULL;
- return outer;
- }
+ /* Check for <init>. */
+
+ if (m->name != utf_init)
+ return NULL;
+
+ /* Create Constructor object. */
+
+ rc = reflect_constructor_new(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 java.lang.reflect.Method object */
+
+ rm = reflect_method_new(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_classref_or_classinfo_println(classref_or_classinfo c)
{
- class_classref_or_classinfo_println(c);
+ class_classref_or_classinfo_print(c);
printf("\n");
}
+#endif
/* class_showconstantpool ******************************************************
utf_display_printable_ascii(c->name);
printf("\n");
- if (c->super.cls) {
+ if (c->super) {
printf("Super: ");
- utf_display_printable_ascii(c->super.cls->name);
+ utf_display_printable_ascii(c->super->name);
printf ("\n");
}
printf("Interfaces:\n");
for (i = 0; i < c->interfacescount; i++) {
printf(" ");
- utf_display_printable_ascii(c->interfaces[i].cls->name);
- printf (" (%d)\n", c->interfaces[i].cls->index);
+ utf_display_printable_ascii(c->interfaces[i]->name);
+ printf (" (%d)\n", c->interfaces[i]->index);
}
printf("Fields:\n");