getMethod/getConstructor native implementation

Artur Biesiadowski abies at pg.gda.pl
Mon Nov 10 13:18:18 PST 1997


I think that I have implemented missing reflection native methods
for java.lang.Class. 
getMethods0, getMethod0, getConstructors0 and getConstructor0
For now no implementation of Method.invoke and Constructor.newInstance,
as I don't know how to convert array to varargs needed for execute_java_*

Bugs:
- no exception info - kaffe omits this special attribute on class load
- null pointer exception on getDeclaredMethods(),
getDeclaredConstructors(); this have to be something simple, if I
find it out, I'll send a patch

Artur
-------------- next part --------------
/*
 * java.lang.Class.c
 *
 * Copyright (c) 1996 T. J. Wilkinson & Associates, London, UK.
 *
 * See the file "lib-license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Written by Tim Wilkinson <tim at tjwassoc.demon.co.uk>, 1996.
 */

#include "config.h"
#include "config-std.h"
#include "config-mem.h"
#include "../../../../kaffe/kaffevm/gtypes.h"
#include "../../../../kaffe/kaffevm/access.h"
#include "../../../../kaffe/kaffevm/constants.h"
#include "../../../../kaffe/kaffevm/object.h"
#include "../../../../kaffe/kaffevm/classMethod.h"
#include "../../../../kaffe/kaffevm/itypes.h"
#include "../../../../kaffe/kaffevm/support.h"
#include "../../../../kaffe/kaffevm/soft.h"
#include "java.io.stubs/InputStream.h"
#include "java.io.stubs/PrintStream.h"
#include "java.lang.stubs/System.h"
#include "java.lang.reflect.stubs/Field.h"
#include "java.lang.reflect.stubs/Method.h"
#include "java.lang.reflect.stubs/Constructor.h"
#include <native.h>
#include "defs.h"

/*
 * Convert string name to class object.
 */
struct Hjava_lang_Class*
java_lang_Class_forName(struct Hjava_lang_String* str)
{
	Hjava_lang_Class* clazz;
	char buf[MAXNAMELEN];

	/* Get string and convert '.' to '/' */
	javaString2CString(str, buf, sizeof(buf));
	classname2pathname(buf, buf);

	clazz = loadClass(makeUtf8Const (buf, strlen(buf)), 0);
	processClass(clazz, CSTATE_OK);

	return (clazz);
}

/*
 * Convert class to string name.
 */
struct Hjava_lang_String*
java_lang_Class_getName(struct Hjava_lang_Class* c)
{
	char buffer[100];
	struct Hjava_lang_String* str;
	int len;
	char* name;
	int i;
	char* ptr;
	char ch;

	len = c->name->length;
	name = len > 100 ? (char*)malloc(len) : buffer;
	ptr = c->name->data;
	for (i = 0; i < len; i++) {
		ch = *ptr++;
		if (ch == '/') {
			ch = '.';
		}
		name[i] = ch;
	}
	str = makeJavaString(name, len);
	if (name != buffer) {
		free (name);
	}
	return (str);
}

/*
 * Create a new instance of the derived class.
 */
struct Hjava_lang_Object*
java_lang_Class_newInstance(struct Hjava_lang_Class* this)
{
	return (execute_java_constructor(0, 0, this, "()V"));
}

/*
 * Return super class.
 */
struct Hjava_lang_Class*
java_lang_Class_getSuperclass(struct Hjava_lang_Class* this)
{
	return (this->superclass);
}

HArrayOfObject* /* [Ljava.lang.Class; */
java_lang_Class_getInterfaces(struct Hjava_lang_Class* this)
{
	HArrayOfObject* obj;
	struct Hjava_lang_Class** ifaces;
	int i;

	obj = (HArrayOfObject*)AllocObjectArray(this->interface_len, "Ljava/lang/Class");
	ifaces = (struct Hjava_lang_Class**)unhand(obj)->body;
	for (i = 0; i < this->interface_len; i++) {
		ifaces[i] = this->interfaces[i];
	}

	return (obj);
}

/*
 * Return the class loader which loaded me.
 */
struct Hjava_lang_ClassLoader*
java_lang_Class_getClassLoader(struct Hjava_lang_Class* this)
{
	return (this->loader);
}

/*
 * Is the class an interface?
 */
jbool
java_lang_Class_isInterface(struct Hjava_lang_Class* this)
{
	return ((this->accflags & ACC_INTERFACE) ? 1 : 0);
}

jbool
java_lang_Class_isPrimitive(struct Hjava_lang_Class* this)
{
	return (CLASS_IS_PRIMITIVE(this));
}

jbool
java_lang_Class_isArray(struct Hjava_lang_Class* this)
{
	return (CLASS_IS_ARRAY(this));
}

Hjava_lang_Class*
java_lang_Class_getComponentType(struct Hjava_lang_Class* this)
{
	Hjava_lang_Class* type;

	if (CLASS_IS_ARRAY(this)) {
		return (CLASS_ELEMENT_TYPE(this));
	}
	else {
		return ((Hjava_lang_Class*)0);
	}
}

jbool
java_lang_Class_isAssignableFrom(struct Hjava_lang_Class* this, struct Hjava_lang_Class* cls)
{
	return (instanceof(this, cls));
}

/*
 * Get primitive class from class name (JDK 1.1)
 */
struct Hjava_lang_Class*
java_lang_Class_getPrimitiveClass(struct Hjava_lang_String* name)
{
	jchar* chrs;

	chrs = &unhand(unhand(name)->value)->body[unhand(name)->offset];
	switch (chrs[0]) {
	case 'b':
		if (chrs[1] == 'y') {
			return (&byteClass);
		}
		if (chrs[1] == 'o') {
			return (&booleanClass);
		}
		break;
	case 'c':
		return (&charClass);
	case 'd':
		return (&doubleClass);
	case 'f':
		return (&floatClass);
	case 'i':
		return (&intClass);
	case 'l':
		return (&longClass);
	case 's':
		return (&shortClass);
	case 'v':
		return (&voidClass);
	}
	return(NULL);
}

/*
 * Is object instance of this class?
 */
jbool
java_lang_Class_isInstance(struct Hjava_lang_Class* this, struct Hjava_lang_Object* obj)
{
	return (soft_instanceof(this, obj));
}

jint
java_lang_Class_getModifiers(struct Hjava_lang_Class* this)
{
	return (this->accflags);
}

jint
java_lang_Class_getSigners()
{
	unimp("java.lang.Class:getSigners unimplemented");
}

jint
java_lang_Class_setSigners()
{
	unimp("java.lang.Class:setSigners unimplemented");
}


int
arrayEquals( HArrayOfObject * first, HArrayOfObject * second )
{
	int i;
	if ( ARRAY_SIZE(first) != ARRAY_SIZE(second) )
		return 0;
	for ( i = ARRAY_SIZE(first) -1; i >= 0; i-- )
	{
		if ( OBJARRAY_DATA(first)[i] != OBJARRAY_DATA(second)[i] )
			return 0;
	}
	return 1;
}

static HArrayOfObject*
parseSignature2Classes( char * signature, struct Hjava_lang_Class** returnType_holder )
{
	HArrayOfObject * array;
	Hjava_lang_Class ** adata;
	Hjava_lang_Class * tclass;
	const char * ptr;
	char buf[CLASSMAXSIG];	/* FIXME - size of buffer? */
	char * bufptr;
	int ins =0;
	int i = 0;
	int arraynest =0;


	ptr = signature;
	while(1)
	{
		switch( *ptr )
		{
			case '(':
				ptr++;
				break;
		    case ')':
				goto knowlength;
			case 'L':
				ins++;
				while( *ptr != ';' )
					ptr++;
				ptr++;
				break;
			case '[':
				ptr++;
				break;
			default:
				ins++;
				ptr++;
				break;
		}
	}

knowlength:

	array = (HArrayOfObject*)AllocObjectArray(ins, "Ljava/lang/Class;");
	ptr = signature;
	adata = (Hjava_lang_Class** ) ARRAY_DATA(array);

	while(1)
	{
		switch( *ptr )
		{
			case '(':
				ptr++;
				continue;
			case ')':
				ptr++;
				goto checkreturn;
			case 'I':
				tclass = &intClass;
				ptr++;
				break;
			case 'Z':
				tclass = &booleanClass;
				ptr++;
				break;
			case 'S':
				tclass = &shortClass;
				ptr++;
				break;
			case 'B':
				tclass = &byteClass;
				ptr++;
				break;
			case 'C':
				tclass = &charClass;
				ptr++;
				break;
			case 'F':
				tclass = &floatClass;
				ptr++;
				break;
			case 'D':
				tclass = &doubleClass;
				ptr++;
				break;
			case 'J':
				tclass = &longClass;
				ptr++;
				break;
			case '[':
				while ( *ptr == '[' )
				{
					ptr++;
					arraynest++;
				}
				continue;
			case 'L':
				ptr++;
				bufptr = buf;
				while ( *ptr != ';' )
					*bufptr++ = *ptr++;
				*bufptr = '\0';
				tclass = lookupClass( buf );
				ptr++;
				break;
			default:
				abort();
		
		}

		while ( arraynest )
		{
			tclass = lookupArray(tclass);
			arraynest--;
		}
		*(adata +i) = tclass;
		i++;
	}

checkreturn:

	assert(arraynest == 0);
	if (returnType_holder)
	{

arrayback:
		switch( *ptr )
		{
			case 'I':
				*returnType_holder = &intClass;
				break;
			case 'Z':
				*returnType_holder = &booleanClass;
				break;
			case 'S':
				*returnType_holder = &shortClass;
				break;
			case 'B':
				*returnType_holder= &byteClass;
				break;
			case 'C':
				*returnType_holder = &charClass;
				break;
			case 'F':
				*returnType_holder = &floatClass;
				break;
			case 'D':
				*returnType_holder = &doubleClass;
				break;
			case 'J':
				*returnType_holder = &longClass;
				break;
			case 'V':
				*returnType_holder = &voidClass;
				break;
			case '[':
				while ( *ptr == '[' )
				{
					arraynest++;
					ptr++;
				}
				goto arrayback;
			case 'L':
				ptr++;
				bufptr = buf;
				while ( *ptr != ';' )
					*bufptr++ = *ptr++;
				*bufptr = '\0';
				*returnType_holder = lookupClass( buf );
				break;
			default:
				abort();
		}

		while ( arraynest )
		{
			*returnType_holder = lookupArray(*returnType_holder);
			arraynest--;
		}
	}
	return array;
}


static struct Hjava_lang_reflect_Method*
makeMethod(struct Hjava_lang_Class* clazz, int slot, HArrayOfObject* parameters,
	struct Hjava_lang_Class * returnType )
{
	Hjava_lang_reflect_Method* method;
	Method* met;

	met = CLASS_METHODS((Hjava_lang_Class*)clazz) + slot;
	method = (Hjava_lang_reflect_Method*)AllocObject("java/lang/reflect/Method");
	unhand(method)->clazz = (struct Hjava_lang_Class*) clazz;
	unhand(method)->slot = slot;
	unhand(method)->name = Utf8Const2JavaString(met->name);
	unhand(method)->returnType = returnType;
	unhand(method)->parameterTypes = parameters;
	unhand(method)->exceptionTypes = (HArrayOfObject*) AllocObjectArray(0,"Ljava/lang/Class");
	/* FIXME - check real exceptions for method - need to change main kaffe */
	return (method);
}

#define IS_CONSTRUCTOR( met )	equalUtf8Consts(met->name, constructor_name)

HArrayOfObject*
java_lang_Class_getMethods0(struct Hjava_lang_Class* this , jint declared)
{
	int count =0;
	Hjava_lang_Class* clas;
	Hjava_lang_Class* returnType;
	Method* met;
	Hjava_lang_reflect_Method** ptr;
	HArrayOfObject* array;
	HArrayOfObject* params;
	int i,nsize;

	if (declared) {
		i = CLASS_NMETHODS((Hjava_lang_Class*)this);
		met = CLASS_METHODS(clas);
		for ( ; --i >= 0;  ++met) {
			if (!IS_CONSTRUCTOR(met)) 
				count++;
		}
	}
	else {
		clas = (Hjava_lang_Class*) this;
		for (; clas != NULL; clas = clas->superclass) {
			met = CLASS_METHODS(clas);
			i = CLASS_NMETHODS(clas);
			for ( ; --i >= 0;  ++met) {
				if ( (met->accflags & ACC_PUBLIC) && 
				( !IS_CONSTRUCTOR(met) ) )
				{
					count++;
				}
			}
		}
	}
	
	array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Method;");
	ptr = (Hjava_lang_reflect_Method**) ARRAY_DATA(array) + count;
	clas = (Hjava_lang_Class*) this;
	do {
		met = CLASS_METHODS(clas);
		nsize = CLASS_NMETHODS(clas);
		for ( i=0; i < nsize;  met++,i++) {
			if (! (met->accflags & ACC_PUBLIC) && ! declared) {
				continue;
			}
			if ( IS_CONSTRUCTOR(met) )
				continue;
			params = parseSignature2Classes(met->signature->data, &returnType);
			*--ptr = makeMethod(clas, i,params,returnType);
		}
		clas = clas->superclass;
	} while (!declared && clas != NULL);

	return (array);
}


struct Hjava_lang_reflect_Method*
java_lang_Class_getMethod0(struct Hjava_lang_Class* this, struct Hjava_lang_String* name, HArrayOfObject* parameters, jint declared)
{
	Hjava_lang_Class* clas;
	HArrayOfObject* mparams;
	Hjava_lang_Class* returnType;

	clas = (Hjava_lang_Class*) this;
	if ( !equalUtf8JavaStrings( constructor_name, name )	 )
	{
		do {
			Method* met = CLASS_METHODS(clas);
			int n = CLASS_NMETHODS(clas);
			int i;
			for (i = 0;  i < n;  ++met, ++i) {
				if (((met->accflags & ACC_PUBLIC) || declared)
					&& equalUtf8JavaStrings (met->name, name)) {
						mparams = parseSignature2Classes(met->signature->data,
							&returnType);
						if ( arrayEquals( parameters, mparams ) )
							return makeMethod(clas, i,mparams,returnType);
				
				}
			}
			clas = clas->superclass;
		} while (!declared && clas != NULL);
	}
	SignalError(0, "java.lang.NoSuchMethodException", ""); /* FIXME */
}


static struct Hjava_lang_reflect_Constructor*
makeConstructor(struct Hjava_lang_Class* clazz, int slot, HArrayOfObject* parameters )
{
	Hjava_lang_reflect_Constructor* constructor;
	Method* met;

	met = CLASS_METHODS((Hjava_lang_Class*)clazz) + slot;
	constructor = (Hjava_lang_reflect_Constructor*)AllocObject("java/lang/reflect/Constructor");
	unhand(constructor)->clazz = (struct Hjava_lang_Class*) clazz;
	unhand(constructor)->slot = slot;
	unhand(constructor)->parameterTypes = parameters;
	unhand(constructor)->exceptionTypes = (HArrayOfObject*) AllocObjectArray(0,"Ljava/lang/Class");
	/* FIXME - check real exceptions for method - need to change main kaffe */
	return (constructor);
}


HArrayOfObject*
java_lang_Class_getConstructors0(struct Hjava_lang_Class* this , jint declared)
{
	int count =0;
	Hjava_lang_Class* clas;
	Hjava_lang_Class* returnType;
	Method* met;
	Hjava_lang_reflect_Constructor** ptr;
	HArrayOfObject* array;
	HArrayOfObject* params;
	int i,nsize;

	if (declared) {
		i = CLASS_NMETHODS((Hjava_lang_Class*)this);
		met = CLASS_METHODS(clas);
		for ( ; --i >= 0;  ++met) {
			if (IS_CONSTRUCTOR(met)) 
				count++;
		}
	}
	else {
		clas = (Hjava_lang_Class*) this;
		for (; clas != NULL; clas = clas->superclass) {
			met = CLASS_METHODS(clas);
			i = CLASS_NMETHODS(clas);
			for ( ; --i >= 0;  ++met) {
				if ( (met->accflags & ACC_PUBLIC) && 
				( IS_CONSTRUCTOR(met)) )
				{
					count++;
				}
			}
		}
	}
	
	array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Constructor;");
	ptr = (Hjava_lang_reflect_Constructor**) ARRAY_DATA(array) + count;
	clas = (Hjava_lang_Class*) this;
	do {
		met = CLASS_METHODS(clas);
		nsize = CLASS_NMETHODS(clas);
		for ( i=0; i < nsize;  met++,i++) {
			if (! (met->accflags & ACC_PUBLIC) && ! declared) {
				continue;
			}
			if ( !IS_CONSTRUCTOR(met) )
				continue;
			params = parseSignature2Classes(met->signature->data, &returnType);
			*--ptr = makeConstructor(clas, i,params);
		}
		clas = clas->superclass;
	} while (!declared && clas != NULL);

	return (array);
}

struct Hjava_lang_reflect_Constructor*
java_lang_Class_getConstructor0(struct Hjava_lang_Class* this, HArrayOfObject* parameters, jint declared)
{
	Hjava_lang_Class* clas;
	HArrayOfObject* mparams;
	Hjava_lang_Class* returnType;

	clas = (Hjava_lang_Class*) this;
	do {
		Method* met = CLASS_METHODS(clas);
		int n = CLASS_NMETHODS(clas);
		int i;
		for (i = 0;  i < n;  ++met, ++i) {
			if (((met->accflags & ACC_PUBLIC) || declared)
				&& IS_CONSTRUCTOR(met)) {
					mparams = parseSignature2Classes(met->signature->data,
						&returnType);
					if ( arrayEquals( parameters, mparams ) )
						return makeConstructor(clas, i,mparams);
			}
		}
		clas = clas->superclass;
	} while (!declared && clas != NULL);
	SignalError(0, "java.lang.NoSuchMethodException", ""); /* FIXME */
}

static
Hjava_lang_reflect_Field*
makeField(struct Hjava_lang_Class* clazz, int slot)
{
	Hjava_lang_reflect_Field* field;
	Field* fld;

	fld = CLASS_FIELDS((Hjava_lang_Class*)clazz) + slot;
	field = (Hjava_lang_reflect_Field*)AllocObject("java/lang/reflect/Field");
	unhand(field)->clazz = (struct Hjava_lang_Class*) clazz;
	unhand(field)->slot = slot;
	unhand(field)->type = (struct Hjava_lang_Class*) fld->type;
	unhand(field)->name = Utf8Const2JavaString(fld->name);
	return (field);
}

HArrayOfObject*
java_lang_Class_getFields0(struct Hjava_lang_Class* clazz, int declared)
{
	int count;
	Hjava_lang_Class* clas;
	Field* fld;
	Hjava_lang_reflect_Field** ptr;
	HArrayOfObject* array;
	int i,nsize;

	if (declared) {
		count = CLASS_NFIELDS((Hjava_lang_Class*)clazz);
	}
	else {
		count = 0;
		clas = (Hjava_lang_Class*) clazz;
		for (; clas != NULL; clas = clas->superclass) {
			fld = CLASS_FIELDS(clas);
			i = CLASS_NFIELDS(clas);
			for ( ; --i >= 0;  ++fld) {
				if (fld->accflags & ACC_PUBLIC) {
					count++;
				}
			}
		}
	}
	array = (HArrayOfObject*)AllocObjectArray(count, "Ljava/lang/reflect/Field;");
	ptr = (Hjava_lang_reflect_Field**) ARRAY_DATA(array) + count;
	clas = (Hjava_lang_Class*) clazz;
	do {
		fld = CLASS_FIELDS(clas);
		nsize = CLASS_NFIELDS(clas);
		for ( i=0; i < nsize;  fld++,i++) {
			if (! (fld->accflags & ACC_PUBLIC) && ! declared) {
				continue;
			}
			*--ptr = makeField(clas, i);
		}
		clas = clas->superclass;
	} while (!declared && clas != NULL);

	return (array);
}

Hjava_lang_reflect_Field*
java_lang_Class_getField0(struct Hjava_lang_Class* clazz, struct Hjava_lang_String* name, int declared)
{
	Hjava_lang_Class* clas;

	clas = (Hjava_lang_Class*) clazz;
	do {
		Field* fld = CLASS_FIELDS(clas);
		int n = CLASS_NFIELDS(clas);
		int i;
		for (i = 0;  i < n;  ++fld, ++i) {
			if (((fld->accflags & ACC_PUBLIC) || declared)
			    && equalUtf8JavaStrings (fld->name, name)) {
				return makeField(clas, i);
			}
		}
		clas = clas->superclass;
	} while (!declared && clas != NULL);
	SignalError(0, "java.lang.NoSuchFieldException", ""); /* FIXME */
}


More information about the kaffe mailing list