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